Hdu 5352 MZL's City (多重匹配)
题目链接:
题目描述:
有n各节点,m个操作。刚开始的时候节点都是相互独立的,一共有三种操作:
1:把所有和x在一个连通块内的未重建过的点全部重建。
2:建立一条双向路(x,y)
3:又发生了地震,p条路被毁。
问最后最多有多少个节点被重建,输出重建节点的最小字典序。
解题思路:
这几天正好在学匹配,但是昨天下午还是没有看出来这个是匹配题目。看了题解扪心自问了自己三次,是不是傻。就是把每个需要重建的节点x拆成k个点,然后对每个拆分后的点和与拆点在同一连通块里面的点建边,然后按照倒序进行匹配,保证字典序最大。
但是匹配好像要比网络流慢好多,改天还是去学一下新姿势的好。
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 const int maxn = 205; 8 const int N = 205*500; 9 vector <int> G[N]; 10 int ans[maxn*2], p[maxn], used[maxn], vis[maxn]; 11 int n, m, k, num, nu, maps[maxn][maxn]; 12 void dfs (int u) 13 {//求连通块内的点 14 vis[u] = 1; 15 p[num ++] = u; 16 for (int i=1; i<=n; i++) 17 if (!vis[i] && maps[u][i]) 18 dfs (i); 19 } 20 bool Find (int u) 21 { 22 for (int i=0; i<G[u].size(); i++) 23 { 24 int v = G[u][i]; 25 if (!vis[v]) 26 { 27 vis[v] = 1; 28 if (!used[v] || Find(used[v])) 29 { 30 used[v] = u; 31 return true; 32 } 33 } 34 } 35 return false; 36 } 37 int hungry () 38 { 39 int res = 0; 40 memset (used, 0, sizeof(used)); 41 for (int i=nu-1; i>=0; i--)//倒序求最大匹配 42 for (int j=i*k; j<(i+1)*k; j++) 43 { 44 memset (vis, 0, sizeof(vis)); 45 if (Find(j)) 46 { 47 res ++; 48 ans[i] ++; 49 } 50 } 51 return res; 52 } 53 int main () 54 { 55 int t; 56 scanf ("%d", &t); 57 while (t --) 58 { 59 scanf ("%d %d %d", &n, &m, &k); 60 memset (maps, 0, sizeof(maps)); 61 for (int i=0; i<N; i++) 62 G[i].clear(); 63 nu = 0; 64 while (m --) 65 { 66 int type, x, y, z; 67 scanf ("%d", &type); 68 if (type == 1) 69 { 70 scanf ("%d", &x); 71 num = 0; 72 memset (vis, 0, sizeof(vis)); 73 dfs (x); 74 for (int i=0; i<num; i++)//建边 75 for (int j=nu*k; j<(nu+1)*k; j++)//拆点 76 G[j].push_back(p[i]); 77 nu ++; 78 } 79 else if (type == 2) 80 { 81 scanf ("%d %d", &x, &y); 82 maps[x][y] = maps[y][x] = 1; 83 } 84 else 85 { 86 scanf ("%d", &z); 87 while (z --) 88 { 89 scanf ("%d %d", &x, &y); 90 maps[x][y] = maps[y][x] = 0; 91 } 92 } 93 } 94 memset (ans, 0, sizeof(ans)); 95 int res = hungry (); 96 printf ("%d\n", res); 97 for (int i=0; i<nu; i++) 98 printf ("%d%c", ans[i], i==nu-1?'\n':' '); 99 } 100 return 0; 101 }
本文为博主原创文章,未经博主允许不得转载。