/************************************************************************/ |找构成二分图完备匹配所必须的边 |思路: 枚举所有边,如果去掉当前边不能构成完备匹配,则是必须的边,否则不是 /************************************************************************/ #include<iostream> using namespace std; const int maxn = 100; int edge_from[maxn]; int edge_to[maxn]; int link[maxn]; int vis[maxn]; int g[maxn*2][maxn*2]; int V, E; bool dfs(int u) { for(int v=1; v<=V; v++) { if(g[u][v+V] && !vis[v]) { vis[v] = 1; if(!link[v] || dfs(link[u])) return true; } } return false; } int maxMatch() { memset(link, 0, sizeof(link)); int ret = 0; for(int i=1; i<=V; i++) { memset(vis, 0, sizeof(vis)); if(dfs(i)) ret++; } return ret; } void solve() { int f, t; for(int i=0; i<E; i++) { f = edge_from[i]; t = edge_to[i]; g[f][t+V] = 0; if(maxMatch() < V) printf("%d - %d/n", f, t); g[f][t+V] = 1; } } int main() { //freopen("in.txt", "r", stdin); while(scanf("%d%d", &V, &E)!=EOF) { if(V==0) break; int f, t; memset(g, 0, sizeof(g)); for(int i=0; i<E; i++) { scanf("%d%d", &f, &t); edge_from[i] = f; edge_to[i] = t; g[f][t+V] = 1; } int ret = maxMatch(); printf("%d/n", ret); solve(); } return 0; } 测试数据 2 - 1; 4 - 3是必须边