UOJ 79 带花树入门
从前一个和谐的班级,所有人都是搞OI的。有 nn 个是男生,有 00 个是女生。男生编号分别为 1,…,n1,…,n。
现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽。每个人至多属于一个小组。
有若干个这样的条件:第 vv 个男生和第 uu 个男生愿意组成小组。
请问这个班级里最多产生多少个小组?
输入格式
第一行两个正整数,n,mn,m。保证 n≥2n≥2。
接下来 mm 行,每行两个整数 v,uv,u 表示第 vv 个男生和第 uu 个男生愿意组成小组。保证 1≤v,u≤n1≤v,u≤n,保证 v≠uv≠u,保证同一个条件不会出现两次。
输出格式
第一行一个整数,表示最多产生多少个小组。
接下来一行 nn 个整数,描述一组最优方案。第 vv 个整数表示 vv 号男生所在小组的另一个男生的编号。如果 vv 号男生没有小组请输出 00。
样例一
input
10 20
9 2
7 6
10 8
3 9
1 10
7 1
10 9
8 6
8 2
8 1
3 1
7 5
4 7
5 9
7 8
10 4
9 1
4 8
6 3
2 5
output
5
9 5 6 10 2 3 8 7 1 4
样例二
input
5 4
1 5
4 2
2 1
4 3
output
2
2 1 4 3 0
限制与约定
1≤n≤500,1≤m≤124750。
时间限制:1s
空间限制:256MB
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 10 using namespace std; 11 12 #define LL long long 13 #define pb push_back 14 #define Set(a, v) memset(a, v, sizeof(a)) 15 #define For(i, a, b) for(int i = (a); i <= (int)(b); i++) 16 #define Forr(i, a, b) for(int i = (a); i >= (int)(b); i--) 17 18 #define MAXN (500+5) 19 20 struct BlossomTree{ 21 vector<int> G[MAXN]; 22 queue<int> q; 23 int n; 24 int pre[MAXN], link[MAXN], col[MAXN], fa[MAXN]; 25 bool vis[MAXN]; 26 27 void init(int rn){ 28 n = rn; 29 Set(link, 0); 30 For(i, 0, n) G[i].clear(); 31 } 32 33 void Addedges(int u, int v){ 34 G[u].pb(v); G[v].pb(u); 35 } 36 37 int find(int x){ 38 return x == fa[x]? x: (fa[x] = find(fa[x])); 39 } 40 41 void Combine(int u, int lca){ 42 while(u != lca){ 43 int f = link[u], g = pre[f]; 44 if(find(g) != lca) pre[g] = f; //put the rever edge 45 if(col[f] == 1) col[f] = 2, q.push(f); 46 fa[find(u)] = find(f); fa[find(f)] = find(g); 47 48 u = pre[link[u]]; 49 } 50 } 51 52 void Contract(int u, int v){ 53 Set(vis, 0); 54 55 int lca = 0; 56 for(int i = u; i; i = pre[link[i]]) i = find(i), vis[i] = true; 57 for(int i = v; i; i = pre[link[i]]){ 58 i = find(i); 59 if(vis[i]){lca = i; break;} 60 } 61 62 if(find(u) != lca) pre[u] = v; 63 if(find(v) != lca) pre[v] = u; 64 Combine(u, lca); Combine(v, lca); 65 } 66 67 void Bfs(int s){ 68 while(!q.empty()) q.pop(); 69 Set(col, 0); Set(pre, 0); 70 For(i, 1, n) fa[i] = i; 71 72 q.push(s); col[s] = 1; 73 while(!q.empty()){ 74 int now = q.front(); q.pop(); 75 76 For(i, 0, G[now].size()-1){ 77 int v = G[now][i]; 78 if(find(now)==find(v) || link[now]==v || col[v]==1) continue; 79 80 if(col[v] == 2) Contract(now, v); 81 else if(link[v]){ 82 pre[v] = now; col[v] = 1; 83 col[link[v]] = 2; 84 q.push(link[v]); 85 }else{ 86 pre[v] = now; 87 88 int g = link[now], f = now, o = v; 89 while(o){ 90 link[f] = o; link[o] = f; 91 o = g; f = pre[o]; g = link[f]; 92 } 93 return; 94 } 95 } 96 } 97 } 98 99 int MaxMatch(){ 100 For(i, 1, n) if(!link[i]) Bfs(i); 101 102 int ret = 0; 103 For(i, 1, n) if(link[i]) ret++; 104 return ret/2; 105 } 106 107 void print(){ 108 printf("%d", link[1]); 109 For(i, 2, n) printf(" %d", link[i]); 110 printf("\n"); 111 } 112 }BT; 113 114 int main(){ 115 int n, m; 116 scanf("%d%d", &n, &m); 117 118 BT.init(n); 119 For(i, 1, m){ 120 int u, v; 121 scanf("%d%d", &u, &v); 122 BT.Addedges(u, v); 123 } 124 125 printf("%d\n", BT.MaxMatch()); 126 BT.print(); 127 128 return 0; 129 }
Miaomiao❤ ++RP