多校第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 }