HDU 3081 Marriage Match II 网络流+二分

来源:互联网 发布:淘宝刷手会被处罚吗 编辑:程序博客网 时间:2024/06/01 08:28

题意:有n个女生和n个男生,一个女生可以和一个和她没有争吵的男生在一起,或者是和这个女生的女闺蜜没有争吵的男生在一起,给你m个点对,每个表示这个女生和这个男生没有争吵,再给你f个点对,表示这两个女生是闺蜜。每一轮游戏女生要选不同的男生,问你这样子的游戏,可以玩多少轮?


想法:可以想到这里要运用并查集处理女生的闺蜜关系,然后二分可以玩的回合数,由于每一回合女生都要找一个不同的男生,那么如果每一个女生都满足这个条件,那么不同的男生数量就是回合数了,网络流建边:设二分回合数是k

1.虚拟source和sink;

2.source到每一个女生连一条容量为k的边;

3.每一个女生向可以连接的男生连一条容量为1的边;

4.每一个男生向sink连一条容量为k的边;

如果最大流等于k*n表示游戏是可以进行到第k轮的。

使用dinic的时候记得加上反向弧优化


#include<iostream>#include<cstring>#include<cstdio>#include<queue>#define inf 0x7fffffffusing namespace std;const int nodes=500+5;const int edges=50000;int n,m,f,s,t;int father[nodes];struct node{    int v,next;    int flow;}e[edges];struct nodee{    int a,b;}person[edges];int head[nodes],cur[nodes],cnt,ff[nodes];void Init(){    memset(head,-1,sizeof(head));    cnt=0;}class Dinic{    public:        int spath()        {            queue<int>q;            while(!q.empty()) q.pop();            memset(dis,-1,sizeof(dis));            dis[s]=0;            q.push(s);            while(!q.empty())            {                int u=q.front();                q.pop();                for(int i=head[u];i+1;i=e[i].next)                {                    int v=e[i].v;                    if(dis[v]==-1&&e[i].flow>0)                    {                        dis[v]=dis[u]+1;                        q.push(v);                    }                }            }            return dis[t]!=-1;        }        int Min(int a,int b)        {            if(a<b) return a;            return b;        }        int dfs(int u,int flow)        {            int cost=0;            if(u==t) return flow;            for(int &i=cur[u];i+1;i=e[i].next)            {                int v=e[i].v;                if(dis[v]==dis[u]+1&&e[i].flow>0)                {                    int min=dfs(v,Min(e[i].flow,flow-cost));                    if(min>0)                    {                        e[i].flow-=min;                        e[i^1].flow+=min;                        cost+=min;                        if(cost==flow) break;                    }                    else dis[v]=-1;                }            }            return cost;        }        int result()        {            int res=0;            while(spath())            {            for(int i=s;i<=t;i++) cur[i]=head[i];                res+=dfs(s,inf);            }            return res;        }    private:        int dis[nodes];}dinic;class UF{    public:        void Init()        {            for(int i=1;i<=200+5;i++)            {                father[i]=i;                rank[i]=1;            }        }        int find_set(int x)        {            if(x!=father[x])            father[x]=find_set(father[x]);            return father[x];        }        void union_set(int a,int b)        {            a=find_set(a);            b=find_set(b);            if(a==b) return;            if(rank[a]>rank[b])            {                rank[a]+=rank[b];                father[b]=a;            }            else             {                rank[b]+=rank[a];                father[a]=b;            }        }        private:            int rank[nodes];}uf;void add(int a,int b,int c){    e[cnt].v=b;    e[cnt].flow=c;    e[cnt].next=head[a];    head[a]=cnt++;        e[cnt].v=a;    e[cnt].flow=0;    e[cnt].next=head[b];    head[b]=cnt++;}void Input(){    scanf("%d%d%d",&n,&m,&f);    for(int i=0;i<m;i++)    {        scanf("%d%d",&person[i].a,&person[i].b);    }    for(int i=1;i<=f;i++)    {        int a,b;        scanf("%d%d",&a,&b);        uf.union_set(a,b);    }    for(int i=1;i<=n;i++)    {    ff[i]=uf.find_set(i);    }}void build_map(int k){    s=0;t=2*n+1;    Init();    for(int i=1;i<=n;i++)    {        add(s,i,k);        add(i+n,t,k);    }    int vis[nodes][nodes];    memset(vis,0,sizeof(vis));    for(int i=0;i<m;i++)    {    int a=person[i].a;    int b=person[i].b;    for(int j=1;j<=n;j++)    {    if(ff[a]==ff[j]&&!vis[j][b])    {    vis[j][b]=1;    add(j,b+n,1);    }    }    }}void treatment(){    int lft=0,rht=n;    int max=0;    while(lft<=rht)    {        int mid=(rht+lft)/2;        build_map(mid);        int k=dinic.result();        if(k==mid*n)         {            max=mid;            lft=mid+1;        }        else        {            rht=mid-1;        }    }    printf("%d\n",max);}int main(){    int t;    scanf("%d",&t);    while(t--)    {        uf.Init();        Input();        treatment();    }    return 0;}


0 0