• hdu3081 Marriage Match II(最大流)


    转载请注明出处: http://www.cnblogs.com/fraud/           ——by fraud

    Marriage Match II

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


    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个男孩,有m个女孩与男孩的关系,代表女孩喜欢男孩,有f个女孩与女孩的关系,代表女孩与女孩是好朋友。

    若女孩i与女孩j是好朋友,而女孩i喜欢男孩k,则女孩j也可以和男孩匹配。即女孩之间的关系是可以传递的,而男孩之间的不可以。

    每对男孩与女孩之间只能匹配一次,问可以进行几轮配对。

    分析:
    先floyd搞好女孩之间的传递关系,然后对于可以配对的女孩与男孩之间连一条容量为1的边,然后二分答案,每次二分之后从源点向各个女孩连容量为二分值的边,从各个男孩向汇点连容量为二分值的边。

      1 //#####################
      2 //Author:fraud
      3 //Blog: http://www.cnblogs.com/fraud/
      4 //#####################
      5 #include <iostream>
      6 #include <sstream>
      7 #include <ios>
      8 #include <iomanip>
      9 #include <functional>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <string>
     13 #include <list>
     14 #include <queue>
     15 #include <deque>
     16 #include <stack>
     17 #include <set>
     18 #include <map>
     19 #include <cstdio>
     20 #include <cstdlib>
     21 #include <cmath>
     22 #include <cstring>
     23 #include <climits>
     24 #include <cctype>
     25 using namespace std;
     26 #define XINF INT_MAX
     27 #define INF 0x3FFFFFFF
     28 #define MP(X,Y) make_pair(X,Y)
     29 #define PB(X) push_back(X)
     30 #define REP(X,N) for(int X=0;X<N;X++)
     31 #define REP2(X,L,R) for(int X=L;X<=R;X++)
     32 #define DEP(X,R,L) for(int X=R;X>=L;X--)
     33 #define CLR(A,X) memset(A,X,sizeof(A))
     34 #define IT iterator
     35 typedef long long ll;
     36 typedef pair<int,int> PII;
     37 typedef vector<PII> VII;
     38 typedef vector<int> VI;
     39 #define MAXN 1010
     40 struct edge{
     41     int to,cap,rev;
     42     edge(int _to,int _cap,int _rev)
     43     {
     44         to=_to;
     45         cap=_cap;
     46         rev=_rev;
     47     }
     48 };
     49 const int MAX_V=5020;
     50 vector<edge>G[MAX_V];
     51 int iter[MAX_V];
     52 int head[MAXN];
     53 int _to[510*510];
     54 int _flow[510*510];
     55 int _next[510*510];
     56 int level[MAX_V];
     57 int tot=0;
     58 void add_edge(int from,int to,int cap)
     59 {
     60     G[from].PB(edge(to,cap,G[to].size()));
     61     G[to].PB(edge(from,0,G[from].size()-1));
     62 }
     63 void Add(int u,int v,int f){
     64     _to[tot]=v;
     65     _flow[tot]=f;
     66     _next[tot]=head[u];
     67     head[u]=tot++;
     68 }
     69 void bfs(int s,int t)
     70 {
     71     CLR(level,-1);
     72     queue<int>q;
     73     level[s]=0;
     74     q.push(s);
     75     while(!q.empty())
     76     {
     77         int u=q.front();
     78         q.pop();
     79         for(int i=0;i<G[u].size();i++)
     80         {
     81             edge &e=G[u][i];
     82             if(e.cap>0&&level[e.to]<0)
     83             {
     84                 level[e.to]=level[u]+1;
     85                 q.push(e.to);
     86             }
     87         }
     88     }
     89 }
     90 int dfs(int v,int t,int f)
     91 {
     92     if(v==t)return f;
     93     for(int &i=iter[v];i<G[v].size();i++)
     94     {
     95         edge &e=G[v][i];
     96         if(e.cap>0&&level[v]<level[e.to])
     97         {
     98             int d=dfs(e.to,t,min(f,e.cap));
     99             if(d>0)
    100             {
    101                 e.cap-=d;;
    102                 G[e.to][e.rev].cap+=d;
    103                 return d;
    104             }
    105         }
    106     }
    107     return 0;
    108 }
    109 int Dinic(int s,int t)
    110 {
    111     int flow=0;
    112     for(;;)
    113     {
    114         bfs(s,t);
    115         if(level[t]<0)return flow;
    116         memset(iter,0,sizeof(iter));
    117         int f;
    118         while((f=dfs(s,t,INF))>0)
    119         {
    120             flow+=f;
    121         }
    122     }
    123 }
    124 
    125 int a[210][210];
    126 
    127 int main()
    128 {
    129     ios::sync_with_stdio(false);
    130     int t;
    131     scanf("%d",&t);
    132     while(t--){
    133         int n,m,f;
    134         scanf("%d%d%d",&n,&m,&f);
    135         tot=0;
    136         for(int i=0;i<MAXN;i++)head[i]=-1;
    137         int u,v;
    138         memset(a,0,sizeof(a));
    139         for(int i=0;i<m;i++){
    140             scanf("%d%d",&u,&v);
    141             a[u][v+n]=1;
    142         }
    143         for(int i=0;i<f;i++){
    144             scanf("%d%d",&u,&v);
    145             a[u][v]=1;
    146             a[v][u]=1;
    147         }
    148         for(int i=1;i<=n+n;i++)a[i][i]=1;
    149         for(int k=1;k<=n+n;k++){
    150             for(int i=1;i<=n+n;i++){
    151                 for(int j=1;j<=n+n;j++){
    152                     a[i][j]=max(a[i][j],a[i][k]&a[k][j]);
    153                 }
    154             }
    155         }
    156         for(int i=1;i<=n;i++){
    157             for(int j=1+n;j<=n+n;j++){
    158                 if(a[i][j])Add(i,j,1);
    159             }
    160         }
    161         int l=0,r=n;
    162         int s=0,t=2*n+1;
    163         int ans=0;
    164         while(l<=r){
    165             int mid=(l+r)>>1;
    166             for(int i=0;i<=2*n+1;i++)G[i].clear();
    167             for(int i=1;i<=2*n;i++){
    168                 int now=head[i];
    169                 while(now!=-1){
    170                     add_edge(i,_to[now],_flow[now]);
    171                     now=_next[now];
    172                 }
    173             }
    174             for(int i=1;i<=n;i++){
    175                 add_edge(s,i,mid);
    176                 add_edge(n+i,t,mid);
    177             }
    178             if(Dinic(s,t)==mid*n){
    179                 ans=mid;
    180                 l=mid+1;
    181             }
    182             else r=mid-1;
    183         }
    184         printf("%d
    ",ans);
    185     }
    186         
    187                     
    188             
    189     return 0;
    190 }
    代码君
  • 相关阅读:
    1052. 卖个萌 (20)
    1051. 复数乘法 (15)
    1050. 螺旋矩阵(25)
    1049. 数列的片段和(20)
    1048. 数字加密(20)
    1047. 编程团体赛(20)
    1046. 划拳(15)
    怎么用js代码改变单选框的选中状态
    Dom操作--全选反选
    Scoket简介
  • 原文地址:https://www.cnblogs.com/fraud/p/4354766.html
Copyright © 2020-2023  润新知