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 }

 

posted @ 2017-01-15 20:52  Miao_miao  阅读(127)  评论(0编辑  收藏  举报