hdu Marriage Match II

  1 /*
  2 hdu       Marriage Match II
  3 题意:n个女孩有n个不是敌对的男孩 其中f对女生彼此是朋友 可以传递的(暗示并查集)
  4       每个女生i也可以和她女朋友j的不敌对的男朋友b配对  每一轮匹配都可以一一对应不重复
  5       问最多可以有几轮M(最大最小 暗示 二分匹配)。
  6 思路:最大流 建图 totals=n+n+2;end=2n+1;
  7       start和女生节点建边 addedge(start,i,M);//边容量为M
  8        男生汇聚终点 addedge(i+n,end,M);//边流量为M
  9        每个女生也可以和她女朋友的不敌对的男朋友配对 
 10        建边addedge(i,b+n,1);//一男一女容量1
 11 结果:M和最大流t关系为 M==t*n 这个为判断条件 二分求出最大M
 12 */
 13 #include <iostream>
 14 #include<cstdio>
 15 #include<cstring>
 16 #include<vector>
 17 #include<queue>
 18 #include<algorithm>
 19 using namespace std;
 20 #define min(a,b) ((a)<(b))?(a):(b)
 21 #define max(a,b) ((a)>(b))?(a):(b)
 22 #define MAXN 6005//尽量开大点
 23 #define MAXM  100002 //M取N的平方倍或者N*9
 24 #define INF 0x3f3f3f3f
 25 int m,n;
 26 int start,end;
 27 struct node
 28 {
 29     int n;//点编号
 30     int w;//点权
 31 }Node[MAXM];//n变m
 32 
 33 //链式前向星
 34 struct enode
 35 {
 36     int t;
 37     int w;                //权值
 38     int c;                //流量
 39 //  int cost;
 40 //    int pre;            //前向指针
 41     int next;
 42 };
 43 
 44     struct enode e[MAXM];
 45     int box[MAXN],ecnt;
 46     //int etail[MAXN];        //尾部
 47     void init()
 48     {
 49         ecnt=0;
 50         memset(box,-1,sizeof(box));
 51     //    memset(etail,-1,sizeof(etail));        //初始化尾部
 52     }
 53     void add(int s,int t)
 54     {
 55          e[ecnt].t=t;
 56          e[ecnt].next=box[s];
 57          box[s]=ecnt++;
 58     }
 59     void addedge(int f,int t,int c)            //流量重载
 60     {
 61         e[ecnt].next=box[f];
 62         e[ecnt].t=t;
 63         e[ecnt].c=c;
 64         box[f]=ecnt++;
 65         e[ecnt].next=box[t];
 66         e[ecnt].t=f;
 67         e[ecnt].c=0;
 68         box[t]=ecnt++;
 69     }
 70 int sap(int s,int t,int N)//最大流问题
 71 {
 72     int gap[MAXN],lvl[MAXN],cur[MAXN],pre[MAXN];
 73     int curflow,ans=0,u,tmp,neck,i;
 74     memset(lvl,0,sizeof(lvl));
 75     memset(gap,0,sizeof(gap));
 76     memset(pre,-1,sizeof(pre));
 77     for(i=0;i<N;i++)
 78         cur[i]=box[i];
 79     gap[0]=N;
 80     u=s;
 81     while(lvl[s]<N)
 82     {
 83         if(u==t)
 84         {
 85             curflow=INF;
 86             for(i=s;i!=t;i=e[cur[i]].t)
 87             {
 88                 if(curflow>e[cur[i]].c)
 89                 {
 90                     neck=i;
 91                     curflow=e[cur[i]].c;
 92                 }
 93             }
 94             for(i=s;i!=t;i=e[cur[i]].t)
 95             {
 96                 tmp=cur[i];
 97                 e[tmp].c-=curflow;
 98                 e[tmp^1].c+=curflow;
 99             }
100             ans+=curflow;
101             u=neck;
102         }
103         for(i=cur[u];i!=-1;i=e[i].next)
104             if(e[i].c && lvl[u]==lvl[e[i].t]+1)
105                 break;
106         if(i!=-1)
107         {
108             cur[u]=i;
109             pre[e[i].t]=u;
110             u=e[i].t;
111         }
112         else
113         {
114             if(--gap[lvl[u]]==0)
115                 break;
116              cur[u]=box[u];
117             for(tmp=N,i=box[u];i!=-1;i=e[i].next)
118                 if(e[i].c)
119                     tmp=min(tmp,lvl[e[i].t]);
120             lvl[u]=tmp+1;
121             gap[lvl[u]]++;
122             if(u!=s)
123                 u=pre[u];
124         }
125     }
126     return ans;
127 }
128 struct S
129 {
130     int a,b;
131 };
132 S p[15000];
133 
134 struct SS
135 {
136     int a,b;
137     int f[MAXN];
138     void init()
139     {
140         for(int i=1;i<=n;i++)f[i]=i;
141     }
142     int find(int x)
143     {
144         int r=x;
145         while(f[r]!=r)
146         r=f[r];
147         f[x]=r;
148         return f[x];
149     }
150     void uni(int x,int y )
151     {
152         x=find(x);
153         y=find(y);
154         if(x!=y)
155         f[x]=y;
156     }
157 };
158 SS  s;
159 void build(int M)
160 {
161     int i,j;
162     init();
163     int _f[200][200];
164     memset(_f,0,sizeof(_f));
165     for(i=1;i<=n;i++)
166     {
167         addedge(start,i,M);
168         addedge(i+n,end,M);
169     }
170     for(i=1;i<=m;i++)
171     {
172         int a=p[i].a,b=p[i].b;
173         for(j=1;j<=n;j++)
174         {
175             if(s.f[a]==s.f[j]&&!_f[j][b])
176             {
177                 addedge(j,b+n,1);
178                 _f[j][b]=1;
179             }
180         }
181     }
182 }
183 int main()
184 {
185      int a,b;
186      int i,j,f;
187      int T;
188 
189 
190      scanf("%d",&T);
191      while(T--)
192      {
193          scanf("%d%d%d",&n,&m,&f);
194          init();
195          start=0;end=2*n+1;
196          for(i=1;i<=m;i++)
197          {
198             scanf("%d%d",&p[i].a,&p[i].b);
199          }
200          s.init();
201          for(i=1;i<=f;i++)
202          {
203              scanf("%d%d",&a,&b);
204              s.uni(a,b);
205          }
206          for(i=1;i<=n;i++)
207          s.f[i]=s.find(i);
208          int L=0,R=n,ans=0;
209          while(L<=R)
210          {
211              int M=(L+R)/2;
212              build(M);
213              if(sap(start,end,end+1)==M*n)
214              {
215                  L=M+1;
216                  ans=M;
217              }else R=M-1;
218          }
219          printf("%d\n",ans);
220      }
221 
222     return 0;
223 }
224 /*
225 1
226 4 5 2
227 1 1
228 2 3
229 3 2
230 4 2
231 4 4
232 1 4
233 2 3
234 
235 
236 
237 Sample Output
238 
239 2
240 
241 */

 

转载于:https://www.cnblogs.com/someonelikeyou/archive/2013/04/24/3041310.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值