「伪模板」主席树(最大流)

这道题,在学主席树的时候就看见了,就加入了收藏计划

最近省选前,填坑,就把这道题切了

主要还是网络流

首先对网络关系处理一下,我用了一下map使它更好处理一下

建图方式:

每个人为一个点

对byx和手气君有的得膜法师进行统计

向byx每个点连边,流量为生命,如果当前节点位主席,生命值加上膜法师数量

同时对手气君的每个点也这样处理

最后对有冲突关系的双方连线,流量为1

这样乖乖的跑一下最大流就好了鸭,嘤嘤嘤

题面

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+7;
const int INF=0x7f7f7f;
//1:j 主席  2:w高人  3:HK港记 4:YYY膜法师  5:E女王 
bool gx[6][6]={{0,0,0,0,0,0},
              {0,0,1,1,0,0},
              {0,0,0,0,1,1},
              {0,0,1,0,0,1},
              {0,1,0,1,0,0},
              {0,1,0,0,1,0}};
int m,n,k,maxflow,cnt=1,tot,ss,t,ans,inc,mtot;
int head[N],dep[N];
map<string,int> mp;
string s[101][2];
bool vis[N];
struct edge
{
    int nx,to,flow;
} e[N];
void add_edge(int a,int b,int flow)
{
    cnt++;e[cnt].nx=head[a];e[cnt].to=b;e[cnt].flow=flow;head[a]=cnt;
    cnt++;e[cnt].nx=head[b];e[cnt].to=a;e[cnt].flow=0;head[b]=cnt;
}
bool bfs(int s,int t)
{
    queue<int> que;que.push(s);
    memset(dep,0,sizeof(dep));dep[s]=1;
    while (!que.empty())
    {
        int x=que.front();que.pop();
        for (int i=head[x];i;i=e[i].nx)
        {
            int y=e[i].to;
            if (dep[y]==0&&e[i].flow)
            {
                dep[y]=dep[x]+1;
                que.push(y);
            }
        }
    }
    if (dep[t]==0) return false;
    else return true;
}
int dfs(int x,int limit,int t)
{
    if (x==t) return limit;
    int used=0;
    for (int i=head[x];i;i=e[i].nx)
    {
        int y=e[i].to;
        if (dep[y]==dep[x]+1&&e[i].flow)
        {
            int di=dfs(y,min(limit-used,e[i].flow),t);
            if (di>0)
            {
                e[i].flow-=di;
                e[i^1].flow+=di;
                used+=di;
                if (used==limit) return limit;
            }
        }
    }
    if (!used) dep[x]=-2;
    return used;
}
void dinic(int s,int t)
{
    while (bfs(s,t)) ans+=dfs(s,INF,t);
}
int main()
{
    scanf("%d%d",&n,&m);ss=N-3;t=N-4;
    for (int i=1;i<=n;i++) cin>>s[i][0];
    for (int i=1;i<=n;i++) cin>>s[i][1];
    mp["J"]=1;mp["W"]=2;mp["HK"]=3;mp["YYY"]=4;mp["E"]=5;
    for (int i=1;i<=n;i++)
     for (int j=1;j<=n;j++)
    {
        int x=mp[s[i][0]],y=mp[s[j][1]];
        if (gx[x][y])add_edge(i,j+n,1);
    }
    for (int i=1;i<=n;i++) if (mp[s[i][0]]==4) tot++;
    for (int j=1;j<=n;j++) if (mp[s[j][1]]==4) mtot++;
    for (int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        if (mp[s[i][0]]==1) add_edge(ss,i,x+tot);
        else add_edge(ss,i,x);
    }
    for (int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        if (mp[s[i][1]]==1) add_edge(i+n,t,x+mtot);
        else add_edge(i+n,t,x);
    }
    dinic(ss,t);
    printf("%d\n",min(ans,m));
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/Hale522520/p/10638895.html
今日推荐