zoukankan      html  css  js  c++  java
  • HDU 3081 最大流+二分

    Marriage Match II

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4021    Accepted Submission(s): 1309


    Problem Description
    Presumably, you all have known the question of stable marriage match. A girl will choose a boy; it is similar as the game of playing house we used to play when we are kids. What a happy time as so many friends playing together. And it is normal that a fight or a quarrel breaks out, but we will still play together after that, because we are kids. 
    Now, there are 2n kids, n boys numbered from 1 to n, and n girls numbered from 1 to n. you know, ladies first. So, every girl can choose a boy first, with whom she has not quarreled, to make up a family. Besides, the girl X can also choose boy Z to be her boyfriend when her friend, girl Y has not quarreled with him. Furthermore, the friendship is mutual, which means a and c are friends provided that a and b are friends and b and c are friend. 
    Once every girl finds their boyfriends they will start a new round of this game—marriage match. At the end of each round, every girl will start to find a new boyfriend, who she has not chosen before. So the game goes on and on.
    Now, here is the question for you, how many rounds can these 2n kids totally play this game?
     
    Input
    There are several test cases. First is a integer T, means the number of test cases. 
    Each test case starts with three integer n, m and f in a line (3<=n<=100,0<m<n*n,0<=f<n). n means there are 2*n children, n girls(number from 1 to n) and n boys(number from 1 to n).
    Then m lines follow. Each line contains two numbers a and b, means girl a and boy b had never quarreled with each other. 
    Then f lines follow. Each line contains two numbers c and d, means girl c and girl d are good friends.
     
    Output
    For each case, output a number in one line. The maximal number of Marriage Match the children can play.
     
    Sample Input
    1
    4 5 2
    1 1
    2 3
    3 2
    4 2
    4 4 
    1 4
    2 3
     
    Sample Output
    2
     
    Author
    starvae
     
    Source
     题意:
    有n个女生n个男生女生可以和她喜欢的男生配对也可以和她的朋友喜欢的男生配对,当所有的人都配对了时游戏结束,要求每一轮游戏中互相已经配对的两个人以后就不能再配对了问可以进行多少轮游戏。
    输入t组数据
    输入n,m,f,对人,m个喜欢关系,f个朋友关系
    输入m行a b 表示女生a喜欢男生b
    输入f行a b 表示女生a和女生b是朋友
    代码:
    //并查集处理配对关系,然后二分轮数,源点连向女生容量为轮数(每人玩这些次),女生连向可以配对的男生,
    //容量为1(只能配对一次),男生连向汇点容量也是轮数。看最大流是否等于n*轮数。
    //今下午脑子坏掉了,二分写挫了wa到死。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int maxn=2200;
    const int inf=0x7fffffff;
    int mp[maxn][maxn],fat[maxn];
    int find(int x){
        return fat[x]==x?x:fat[x]=find(fat[x]);
    }
    void connect(int x,int y){
        int xx=find(x),yy=find(y);
        if(xx!=yy) fat[yy]=xx;
    }
    struct Edge{
        int from,to,cap,flow;
        Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
    };
    struct Dinic{
        int n,m,s,t;
        vector<Edge>edges;
        vector<int>g[maxn];
        bool vis[maxn];
        int d[maxn];
        int cur[maxn];
        void init(int n){
            this->n=n;
            for(int i=0;i<n;i++) g[i].clear();
            edges.clear();
        }
        void Addedge(int from,int to,int cap){
            edges.push_back(Edge(from,to,cap,0));
            edges.push_back(Edge(to,from,0,0));//反向弧
            m=edges.size();
            g[from].push_back(m-2);
            g[to].push_back(m-1);
        }
        bool Bfs(){
            memset(vis,0,sizeof(vis));
            queue<int>q;
            q.push(s);
            d[s]=0;
            vis[s]=1;
            while(!q.empty()){
                int x=q.front();q.pop();
                for(int i=0;i<(int)g[x].size();i++){
                    Edge &e=edges[g[x][i]];
                    if(!vis[e.to]&&e.cap>e.flow){
                        vis[e.to]=1;
                        d[e.to]=d[x]+1;
                        q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
        int Dfs(int x,int a){
            if(x==t||a==0) return a;
            int flow=0,f;
            for(int&i=cur[x];i<(int)g[x].size();i++){
                Edge &e=edges[g[x][i]];
                if(d[x]+1==d[e.to]&&(f=Dfs(e.to,min(a,e.cap-e.flow)))>0){
                    e.flow+=f;
                    edges[g[x][i]^1].flow-=f;
                    flow+=f;
                    a-=f;
                    if(a==0) break;
                }
            }
            return flow;
        }
        int Maxflow(int s,int t){
            this->s=s;this->t=t;
            int flow=0;
            while(Bfs()){
                memset(cur,0,sizeof(cur));
                flow+=Dfs(s,inf);
            }
            return flow;
        }
    }dc;
    bool solve(int n,int mid){
        dc.init(2*n+2);
        for(int i=1;i<=n;i++){
            dc.Addedge(0,i,mid);
            for(int j=n+1;j<=2*n;j++)if(mp[i][j])
                dc.Addedge(i,j,1);
            dc.Addedge(i+n,2*n+1,mid);
        }
        return n*mid==dc.Maxflow(0,2*n+1);
    }
    int main()
    {
        int t,n,m,f;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d%d",&n,&m,&f);
            int a,b;
            memset(mp,0,sizeof(mp));
            for(int i=1;i<=2*n;i++) fat[i]=i;
            for(int i=1;i<=m;i++){
                scanf("%d%d",&a,&b);
                mp[a][b+n]=1;
            }
            for(int i=1;i<=f;i++){
                scanf("%d%d",&a,&b);
                connect(a,b);
            }
            for(int i=1;i<=n;i++){
                for(int j=i+1;j<=n;j++){
                    if(find(i)==find(j))
                        for(int k=n+1;k<=2*n;k++)
                            mp[i][k]=mp[j][k]=(mp[i][k]||mp[j][k]);
                }
            }
            int l=0,r=n,mid,ans=0;
            while(l<=r){
                mid=(l+r)/2;
                if(solve(n,mid)){
                    ans=mid;
                    l=mid+1;
                }
                else r=mid-1;
            }
            printf("%d
    ",ans); 
        }
        return 0;
    }
  • 相关阅读:
    [转]简单理解php的socket编程
    github 生成token的方法
    win7升级powershell【转】
    PHP的反射机制 【转】
    jquery幻灯片插件slick演示
    织梦生成的时候“你指定的文件名有问题,无法创建文件”解决方案【转】
    dedecms下的tplcache模板缓存[转]
    dede织梦data目录正确迁移及引起的问题解决方法【转】
    C# 判断是否是在设计模式下有效的方法
    C# 操作计算机用户权限
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/6930861.html
Copyright © 2011-2022 走看看