从前一个和谐的班级,所有人都是搞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≤5001≤n≤500,1≤m≤1247501≤m≤124750。
时间限制:1s1s
空间限制:256MB256MB
下载
一般图最大匹配的模板,本人技术水平有限,感觉写不出网上那么好的博客,所以就贴一个吧。
一般图最大匹配
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e3 + 5;
const int maxm = 124750 + 5;
int n, m, u, v;
struct edge {
int v, next;
}e[maxm << 1];
int head[maxn], cnt, fa[maxn];
void adde(const int &u, const int &v) {
e[++cnt] = (edge) {v, head[u]};
head[u] = cnt;
}
namespace DSU {
int fa[maxn];
void init(int x) {for(register int i = 1; i <= x; ++i) fa[i] = i;}
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);}
void combine(int a, int b) {fa[find(a)] = find(b);}
}
int type[maxn], match[maxn], pre[maxn], tid[maxn], id;
int LCA(int u, int v) {
for(++id;;swap(u, v))
if(u) {
u = DSU::find(u);
if(tid[u] == id) return u;
else tid[u] = id, u = pre[match[u]];
}
}
void Bloom(int u, int v, int lca, queue<int > * q) {
while(DSU::find(u) != lca) {
pre[u] = v, v = match[u];
if(DSU::find(u) == u) DSU::fa[u] = lca;
if(DSU::find(v) == v) DSU::fa[v] = lca;
if(type[v] == 1) type[v] = 0, q -> push(v);
u = pre[v];
}
}
bool AGM(int u) { // augmentation;
DSU::init(n);
memset(type, -1, sizeof(int) * (n + 1));
memset(pre, 0, sizeof(int) * (n + 1));
queue<int > q; q.push(u);
while(!q.empty()) {
int u = q.front();
q.pop();
for(register int i = head[u]; i; i = e[i].next) {
int v = e[i].v;
if(DSU::find(u) == DSU::find(v)) continue;
if(type[v] == -1) {
if(!match[v]) {
while(u) {
int t = match[u];
match[match[v] = u] = v;
u = pre[v = t];
}
return 1;
}
type[v] = 1, pre[v] = u;
type[match[v]] = 0, q.push(match[v]);
} else if(type[v] == 0) {
int lca = LCA(u, v);
Bloom(u, v, lca, &q);
Bloom(v, u, lca, &q);
}
}
}
return 0;
}
int ans = 0;
int main() {
scanf("%d%d", &n, &m);
for(register int i = 1; i <= m; ++i)
scanf("%d%d", &u, &v), adde(u, v), adde(v, u);
for(register int i = 1; i <= n; ++i)
if(!match[i]) ans += AGM(i);
printf("%d\n", ans);
for(register int i = 1; i <= n; ++i)
printf("%d ", match[i]);
return 0;
} #include
#include
#include
#include
using namespace std;
const int maxn = 1e3 + 5;
const int maxm = 124750 + 5;
int n, m, u, v;
struct edge {
int v, next;
}e[maxm << 1];
int head[maxn], cnt, fa[maxn];
void adde(const int &u, const int &v) {
e[++cnt] = (edge) {v, head[u]};
head[u] = cnt;
}
namespace DSU {
int fa[maxn];
void init(int x) {for(register int i = 1; i <= x; ++i) fa[i] = i;}
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);}
void combine(int a, int b) {fa[find(a)] = find(b);}
}
int type[maxn], match[maxn], pre[maxn], tid[maxn], id;
int LCA(int u, int v) {
for(++id;;swap(u, v))
if(u) {
u = DSU::find(u);
if(tid[u] == id) return u;
else tid[u] = id, u = pre[match[u]];
}
}
void Bloom(int u, int v, int lca, queue<int > * q) {
while(DSU::find(u) != lca) {
pre[u] = v, v = match[u];
if(DSU::find(u) == u) DSU::fa[u] = lca;
if(DSU::find(v) == v) DSU::fa[v] = lca;
if(type[v] == 1) type[v] = 0, q -> push(v);
u = pre[v];
}
}
bool AGM(int u) {
DSU::init(n);
memset(type, -1, sizeof(int) * (n + 1));
memset(pre, 0, sizeof(int) * (n + 1));
queue q; q.push(u);
while(!q.empty()) {
int u = q.front();
q.pop();
for(register int i = head[u]; i; i = e[i].next) {
int v = e[i].v;
if(DSU::find(u) == DSU::find(v)) continue;
if(type[v] == -1) {
if(!match[v]) {
while(u) {
int t = match[u];
match[match[v] = u] = v;
u = pre[v = t];
}
return 1;
}
type[v] = 1, pre[v] = u;
type[match[v]] = 0, q.push(match[v]);
} else if(type[v] == 0) {
int lca = LCA(u, v);
Bloom(u, v, lca, &q);
Bloom(v, u, lca, &q);
}
}
}
return 0;
}
int ans = 0;
int main() {
scanf("%d%d", &n, &m);
for(register int i = 1; i <= m; ++i)
scanf("%d%d", &u, &v), adde(u, v), adde(v, u);
for(register int i = 1; i <= n; ++i)
if(!match[i]) ans += AGM(i);
printf("%d\n", ans);
for(register int i = 1; i <= n; ++i)
printf("%d ", match[i]);
return 0;
}
rockdu
没有帐号? 立即注册