hdu4685Prince and Princess(二分图最大匹配+SCC)

多校第8场UESTC的题目,长沙网络赛I题。

【题意】

给定二分图,求哪些边选择作为匹配仍然可以得到最大匹配。

【分析】

和http://www.cnblogs.com/wangsouc/articles/3360635.html思路相同,

【吐槽】

写完测试样例,其实答案是对的,我把Input看成Output以为错了。。。跪了2个多小时。。囧。。

经常犯二。

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<math.h>
  5 #include<algorithm>
  6 #include<queue>
  7 
  8 using namespace std;
  9 
 10 const int maxn = 1010;
 11 const int maxe = 1001000;
 12 struct edge{
 13     int u;
 14     int v;
 15     int next;
 16 }e[maxe*2],seq[maxe];
 17 int last[maxn];
 18 int tot;
 19 int E;
 20 int leee[maxn];
 21 
 22 void add(int u,int v)
 23 {
 24     e[tot].v = v;
 25     e[tot].next = last[u];
 26     last[u] = tot++;
 27     return ;
 28 }void addd(int u,int v)
 29 {
 30     seq[E].v = v;
 31     seq[E].next = leee[u];
 32     leee[u] = E++;
 33     return ;
 34 }
 35 int n,m;
 36 
 37 const int inf = 1 << 28;
 38 int cx[maxn];
 39 int cy[maxn];
 40 int nx, ny;
 41 int dx[maxn];
 42 int dy[maxn];
 43 int dis;
 44 bool vis[maxn];
 45 
 46 queue<int>Q;
 47 bool search()
 48 {
 49     dis = inf;
 50     while (!Q.empty())
 51         Q.pop();
 52     memset(dx,-1,sizeof(dx));
 53     memset(dy,-1,sizeof(dy));
 54     for (int i=1;i<=nx;i++)
 55     {
 56         if (cx[i]==-1){
 57             Q.push(i);
 58             dx[i] = 0;
 59         }
 60     }
 61     while (!Q.empty()){
 62         int u = Q.front();
 63         Q.pop();
 64         if (dx[u] > dis)
 65             break;
 66         for (int j = last[u];j!=-1;j=e[j].next){
 67             int v= e[j].v;
 68             if (dy[v]==-1){
 69                 dy[v] = dx[u] + 1;
 70                 if (cy[v] == -1){
 71                     dis = dy[v];
 72                 }else{
 73                     dx[cy[v]] = dy[v] + 1;
 74                     Q.push(cy[v]);
 75                 }
 76             }
 77         }
 78     }
 79     return dis != inf;
 80 }
 81 bool find(int u)
 82 {
 83     for (int j = last[u];j!=-1;j=e[j].next){
 84         int v = e[j].v;
 85         if (!vis[v] && dy[v] == dx[u]+1){
 86             vis[v] = 1;
 87             if (cy[v] !=-1 && dy[v] == dis){
 88                 continue;
 89             }
 90             if (cy[v]==-1 || find(cy[v])){
 91                 cy[v] = u;
 92                 cx[u] = v;
 93                 return true;
 94             }
 95         }
 96     }
 97     return false;
 98 }
 99 int MaxMatch()
100 {
101     nx = n;
102     ny = m;
103     int res = 0;
104     memset(cx,-1,sizeof(cx));
105     memset(cy,-1,sizeof(cy));
106     while (search()){
107         memset(vis,0,sizeof(vis));
108         for (int i=1;i<=nx;i++){
109             if (cx[i] == -1){
110                 res += find(i);
111             }
112         }
113     }
114     return res;
115 }
116 
117 
118 int dfn[maxn],low[maxn];
119 int color[maxn];
120 bool instack[maxn];
121 int ind[maxn],oud[maxn];
122 int st[maxn],top;
123 int scnt,cnt;
124 void tarjan(int u)
125 {
126     int i,v,x;
127     dfn[u]=low[u]=cnt++;
128     st[++top]=u;
129     instack[u]=1;
130     for(i=last[u]; i!=-1; i=e[i].next)
131     {
132         v=e[i].v;
133         if (dfn[v]==-1)
134         {
135             tarjan(v);
136             low[u]=min(low[u],low[v]);
137         }
138         else if(instack[v]) low[u]=min(low[u],dfn[v]);
139     }
140     if (dfn[u] == low[u])
141     {
142         do
143         {
144             x=st[top--];
145             instack[x]=0;
146             color[x]=scnt;
147         }
148         while (x!=u);
149         scnt++;
150     }
151 }
152 void base(int nn)
153 {
154     int i,j,u,v;
155     cnt=0;
156     scnt=0;
157     top=0;
158     memset(dfn,-1,sizeof(dfn));
159     memset(instack,0,sizeof(instack));
160     for(i=1; i<=nn; i++)
161         if (dfn[i]==-1)
162         {
163             tarjan(i);
164         }
165     return ;
166 }
167 
168 
169 
170 int ans[maxe];
171 int total;
172 int path[maxn];
173 
174 
175 int main()
176 {
177     int cas, cast = 0;
178     scanf("%d", &cas);
179     while (cas--)
180     {
181         scanf("%d%d", &n, &m);
182         memset(last,-1,sizeof(last));
183         memset(leee,-1,sizeof(leee));
184         tot = 0;
185         E = 0;
186         for (int i=1;i<=n;i++)
187         {
188             int k;
189             scanf("%d", &k);
190             for (int j=1;j<=k;j++){
191                 int x;
192                 scanf("%d", &x);
193                 add(i,x);
194                 addd(i,x);
195             }
196         }
197         MaxMatch();
198 
199         memset(last,-1,sizeof(last));
200         tot = 0;
201 
202         for (int i=1;i<=n;i++){
203             for (int j=leee[i];j!=-1;j=seq[j].next){
204                 int v = seq[j].v;
205                 if (cx[i] == v){
206                     add(v+n,i);
207                 }else{
208                     add(i,v+n);
209                 }
210             }
211         }
212         for (int i=1;i<=n;i++){
213             if (cx[i] == -1){
214                 add(n+m+1,i);
215             }else{
216                 add(i, n+m+1);
217             }
218         }
219         for (int i=1;i<=m;i++)
220         {
221             if (cy[i]==-1){
222                 add(n+i, n+m+2);
223             }else{
224                 add(n+m+2,n+i);
225             }
226         }
227         for (int i=1;i<=n;i++){
228          //   printf("cx %d %d\n",i,cx[i]);
229         }
230         for (int i=1;i<=m;i++){
231         //    printf("cy %d %d\n",i,cy[i]);
232         }
233 
234         base(n+m+2);
235 
236         printf("Case #%d:\n",++cast);
237         for (int i=1;i<=n;i++){
238             int ans = 0;
239             for (int j=leee[i];j!=-1;j=seq[j].next){
240                 int v = seq[j].v;
241                 if (cx[i]==v || color[i] == color[v+n]){
242                     path[ans++] = v;
243                 }
244             }
245             printf("%d",ans);
246             sort(path,path+ans);
247             for (int i=0;i<ans;i++){
248                 printf(" %d",path[i]);
249             }
250             printf("\n");
251         }
252     }
253     return 0;
254 }
hdu4685

 

转载于:https://www.cnblogs.com/wangsouc/articles/3360937.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值