hdu4685 n个男生m个女生问男生可以娶哪些女生使最大匹配数不改变:二分图匹配/tarjan
(男生喜欢特定的女生,女生可以嫁给任何男生=
先按题意求出最大匹配,然后在左边增加n-res个虚拟男生喜欢所有女生,m-res个虚拟女生喜欢所有男生,再求最大匹配,这个时候肯定是个完全匹配,求匹配只是确定新的二分图里面每个男生对应的女生是谁=
在所有女生女生里面建有向图,将某男生匹配的女生连向所有他喜欢的女生一条边,求一遍tarjan,这样所有和他匹配的女生在一个连通分量里面的女生都可以选=
为什么?因为可以间接交换而不改变匹配数!
本来明白思路之后很快就打完了,却一直TLE,T了一个下午wocao!百思不得其解!
然后在一下午的修改,查找后终于发现了bug,在代码的92行,刚开始我没加&&g[i][j]这个条件,当时打代码没细想,觉得在一个环就肯定能交换,忘了男生要喜欢这个女生==but!艹!特么给我wa还能解释,TLE我现在还是不能接受,好醉===
1 #include<stdio.h> 2 #include<string.h> 3 #include<stack> 4 #include<vector> 5 #include<algorithm> 6 using namespace std; 7 stack<int>s; 8 vector<int>G[1105]; 9 int g[1105][1105],y[1105],link[1105],linky[1105]; 10 int dfs_clock,scc_cnt,pre[1105],lowlink[1105],sccno[1105]; 11 int n1,n2,d[1105],ans[1105][1105]; 12 int dfs(int u){ 13 for (int i=1;i<=n2;i++) 14 if (g[u][i]&&!y[i]){ 15 y[i]=1; 16 if (!link[i]||dfs(link[i])){ 17 link[i]=u; 18 return 1; 19 } 20 } 21 return 0; 22 } 23 int maxmatch(){ 24 memset(link,0,sizeof(link)); 25 int ans=0; 26 for (int i=1;i<=n1;i++){ 27 memset(y,0,sizeof(y)); 28 if (dfs(i)) ans++; 29 } 30 return ans; 31 } 32 void tarjan(int u){ 33 int v; 34 pre[u]=lowlink[u]=++dfs_clock; 35 s.push(u); 36 for (int i=0;i<G[u].size();i++){ 37 v=G[u][i]; 38 if (!pre[v]){ 39 tarjan(v); 40 lowlink[u]=min(lowlink[u],lowlink[v]); 41 } 42 else if (!sccno[v]) 43 lowlink[u]=min(lowlink[u],pre[v]); 44 } 45 if (lowlink[u]==pre[u]){ 46 scc_cnt++; 47 while (1){ 48 v=s.top(); s.pop(); 49 sccno[v]=scc_cnt; 50 if (v==u) break; 51 } 52 } 53 } 54 int main() 55 { 56 int T,t,x,i,j,n,m,res,u; 57 scanf("%d",&T); 58 for (t=1;t<=T;t++){ 59 scanf("%d%d",&n,&m); 60 memset(g,0,sizeof(g)); 61 for (i=1;i<=n;i++){ 62 scanf("%d",&x); 63 for (j=1;j<=x;j++){ 64 scanf("%d",&u); 65 g[i][u]=1; 66 } 67 } 68 n1=n; n2=m; 69 res=maxmatch(); 70 n1=n2=n+m-res; 71 for (i=n+1;i<=n1;i++) 72 for (j=1;j<=n2;j++) g[i][j]=1; 73 for (j=m+1;j<=n2;j++) 74 for (i=1;i<=n1;i++) g[i][j]=1; 75 maxmatch(); 76 for (i=1;i<=n2;i++) linky[link[i]]=i; 77 for (i=1;i<=n2;i++) G[i].clear(); 78 for (i=1;i<=n1;i++){ 79 u=linky[i]; 80 for (j=1;j<=n2;j++) 81 if (j!=linky[i]&&g[i][j]) G[u].push_back(j); 82 } 83 dfs_clock=scc_cnt=0; 84 while (!s.empty()) s.pop(); 85 memset(sccno,0,sizeof(sccno)); 86 memset(pre,0,sizeof(pre)); 87 for (i=1;i<=n2;i++) 88 if (!pre[i]) tarjan(i); 89 memset(d,0,sizeof(d)); 90 for (i=1;i<=n;i++) 91 for (j=1;j<=m;j++) 92 if (sccno[j]==sccno[linky[i]]&&g[i][j]) ans[i][++d[i]]=j; 93 printf("Case #%d:\n",t); 94 for (i=1;i<=n;i++){ 95 printf("%d",d[i]); 96 for (j=1;j<=d[i];j++) printf(" %d",ans[i][j]); 97 printf("\n"); 98 } 99 } 100 return 0; 101 }