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 }
View Code

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685

posted on 2015-04-08 19:24  xiao_xin  阅读(348)  评论(0编辑  收藏  举报

导航