http://acm.hdu.edu.cn/showproblem.php?pid=4687
题意为n个人,m个组合,给出m个组合成员,每个人最多在一个组合,求出在能形成最多数量组合的情况下多余的组合
带花树跑出最大匹配数ans+枚举删除每条边若为ans-1则为必须的边,否则为多余的边
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
const int maxm = 150;
deque<int> Q;
bool g[maxn][maxn], inque[maxn], inblossom[maxn], inpath[maxn];
int match[maxn], pre[maxn], base[maxn];
int findAncestor(int u, int v) {
memset(inpath, false, sizeof(inpath));
while(true) {
u = base[u];
inpath[u] = true;
if(match[u] == -1) break;
u = pre[match[u]];
}
while(true) {
v = base[v];
if(inpath[v]) return v;
v = pre[match[v]];
}
}
void reset(int u, int anc) {
while(u != anc) {
int v = match[u];
inblossom[base[u]] = 1;
inblossom[base[v]] = 1;
v = pre[v];
if(base[v] != anc) pre[v] = match[u];
u = v;
}
}
void contract(int u, int v, int n) {
int anc = findAncestor(u, v);
memset(inblossom, 0, sizeof(inblossom));
reset(u, anc);
reset(v, anc);
if(base[u] != anc) pre[u] = v;
if(base[v] != anc) pre[v] = u;
for(int i = 1; i <= n; ++i)
if(inblossom[base[i]]) {
base[i] = anc;
if(!inque[i]) {
Q.push_back(i);
inque[i] = 1;
}
}
}
bool bfs(int S, int n) {
for(int i = 0; i <= n; ++i) pre[i] = -1, inque[i] = 0, base[i] = i;
Q.clear();
Q.push_back(S);
inque[S] = 1;
while(!Q.empty()) {
int u = Q.front();
Q.pop_front();
for(int v = 1; v <= n; ++v) {
if(g[u][v] && base[v] != base[u] && match[u] != v) {
if(v == S || (match[v] != -1 && pre[match[v]] != -1)) contract(u, v, n);
else if(pre[v] == -1) {
pre[v] = u;
if(match[v] != -1) Q.push_back(match[v]), inque[match[v]] = 1;
else {
u = v;
while(u != -1) {
v = pre[u];
int w = match[v];
match[u] = v;
match[v] = u;
u = w;
}
return true;
}
}
}
}
}
return false;
}
int solve(int n) {
memset(match, -1, sizeof(match));
int ans = 0;
for(int i = 1; i <= n; ++i)
if(match[i] == -1 && bfs(i, n))
ans++;
return ans;
}
pair<int, int> q[maxm];
int vis[maxm];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
while(cin >> n >> m) {
memset(g, false, sizeof(g));
int u, v;
for(int i = 0; i < m; ++i) {
cin >> u >> v;
q[i].first = u, q[i].second = v;
g[u][v] = g[v][u] = 1;
}
memset(vis, 0, sizeof(vis));
int ans = solve(n), cnt = 0, flg = 0;
for(int i = 0; i < m; ++i) {
memset(g, false, sizeof(g));
for(int j = 0; j < m; ++j) {
if(q[j].first == q[i].first) continue;
if(q[j].first == q[i].second) continue;
if(q[j].second == q[i].first) continue;
if(q[j].second == q[i].second) continue;
g[q[j].first][q[j].second] = g[q[j].second][q[j].first] = 1;
}
if(solve(n) == ans - 1)
vis[i] = 1;
else cnt++;
}
cout << cnt << endl;
for(int i = 0; i < m; ++i) {
if(!vis[i] && !flg) {
cout << (i + 1);
flg = 1;
}
else if(!vis[i]) cout << " " << i + 1;
}
cout << endl;
}
}