标签:can push lin oge ++ contains case 标记 std
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081
题目:
1 //HDU 3081 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 9 const int N=2333; 10 const int M=233333; 11 const int INF=0x3f3f3f3f; 12 int n,m,f,s,t,cnt; 13 int Head[N],Depth[N],cur[N],Father[N]; 14 int Next[M],V[M],W[M]; 15 bool Map[N][N]; 16 17 int Find(int x){return x==Father[x]?x:Father[x]=Find(Father[x]);} 18 void Union(int x,int y){ 19 int fx=Find(x),fy=Find(y); 20 if(fx!=fy){ 21 Father[fx]=fy; 22 } 23 } 24 25 void init(){ 26 cnt=-1; 27 memset(Head,-1,sizeof(Head)); 28 memset(Next,-1,sizeof(Next)); 29 } 30 31 void add_edge(int u,int v,int w){ 32 cnt++;Next[cnt]=Head[u];V[cnt]=v;W[cnt]=w;Head[u]=cnt; 33 cnt++;Next[cnt]=Head[v];V[cnt]=u;W[cnt]=0;Head[v]=cnt; 34 } 35 36 bool bfs(){ 37 queue <int> Q; 38 while(!Q.empty()) Q.pop(); 39 memset(Depth,0,sizeof(Depth)); 40 Depth[s]=1; 41 Q.push(s); 42 while(!Q.empty()){ 43 int u=Q.front();Q.pop(); 44 for(int i=Head[u];i!=-1;i=Next[i]){ 45 if((W[i]>0)&&(Depth[V[i]]==0)){ 46 Depth[V[i]]=Depth[u]+1; 47 Q.push(V[i]); 48 } 49 } 50 } 51 if(Depth[t]==0) return 0; 52 return 1; 53 } 54 55 int dfs(int u,int dist){ 56 if(u==t) return dist; 57 for(int& i=cur[u];i!=-1;i=Next[i]){ 58 if((Depth[V[i]]==Depth[u]+1)&&W[i]!=0){ 59 int di=dfs(V[i],min(dist,W[i])); 60 if(di>0){ 61 W[i]-=di; 62 W[i^1]+=di; 63 return di; 64 } 65 } 66 } 67 return 0; 68 } 69 70 int Dinic(){ 71 int ans=0; 72 while(bfs()){ 73 for(int i=0;i<=2*n+1;i++) cur[i]=Head[i]; 74 while(int d=dfs(s,INF)) ans+=d; 75 } 76 return ans; 77 } 78 79 int check(int k){ 80 init(); 81 for(int i=1;i<=n;i++) 82 for(int j=1+n;j<=2*n;j++) 83 if(Map[i][j]) add_edge(i,j,1); 84 85 for(int i=1;i<=n;i++) add_edge(s,i,k); 86 for(int i=1+n;i<=2*n;i++) add_edge(i,t,k); 87 88 if(Dinic()==k*n) return 1; 89 else return 0; 90 } 91 92 int main(){ 93 int T,a,b; 94 scanf("%d",&T); 95 while(T--){ 96 memset(Map,0,sizeof(Map)); 97 for(int i=0;i<N;i++) Father[i]=i; 98 scanf("%d %d %d",&n,&m,&f); 99 for(int i=1;i<=m;i++){ 100 scanf("%d %d",&a,&b); 101 Map[a][b+n]=1; 102 } 103 for(int i=1;i<=f;i++){ 104 scanf("%d %d",&a,&b); 105 Union(a,b); 106 } 107 for(int i=1;i<=n;i++) 108 for(int j=i+1;j<=n;j++) 109 if(Find(i)==Find(j)){ 110 for(int k=1+n;k<=2*n;k++){ 111 Map[i][k]=Map[j][k]=(Map[i][k]||Map[j][k]); 112 } 113 } 114 int s=0;t=2*n+1; 115 int l=0,r=111,mid; 116 while(r-l>1){ 117 mid=(l+r)/2; 118 if(check(mid)) l=mid; 119 else r=mid; 120 } 121 printf("%d\n",l); 122 } 123 return 0; 124 }
//还有一种匈牙利的方法(二分图最大匹配),如果跑完完全匹配,答案+1,拆掉这种方案的所有边,然后接着跑,直到没有能完全匹配。
HDU 3081 Marriage Match II(网络流+并查集+二分答案)
标签:can push lin oge ++ contains case 标记 std
原文地址:http://www.cnblogs.com/Leonard-/p/7899200.html