二分图的最大匹配(最小路径覆盖,最小点覆盖)

/******************************************************************************* 匈牙利算法:参考算法《算法设计技巧与分析》p444 输入:g[][]二维数组为图的链接矩阵,N为点的个数 输出:ans最大匹配值,pre[]数组:pre[i]表示与点i匹配的点 ********************************************************************************/ const int MAXN = 200+5; int N; int g[MAXN][MAXN]; bool used[MAXN]; int pre[MAXN]; //深搜找交错路径 bool dfs(int t) { int i, tmp; for(i = N+1; i <= 2*N; i++) if(g[t][i] && !used[i]) { used[i] = true; if(pre[i]== -1 || dfs(pre[i])) { pre[i] = t; return true; } } return false; } int Match() { int i, ans = 0; memset(pre, -1, sizeof(pre)); for(i = 1; i <= N; i++) { memset(used, false, sizeof(used)); if(dfs(i)) ans++; } return ans; }

 

/* ID: linjd821 LANG: C++ TASK: air raid(pku) */ /* //有向无环图的最小路径覆盖 //1:拆点+求最大二分匹配M //2: 最小路径覆盖就是N-M */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; /******************************************************************************* 匈牙利算法:参考算法《算法设计技巧与分析》p444 输入:g[][]二维数组为图的链接矩阵,N为点的个数 输出:ans最大匹配值,pre[]数组:pre[i]表示与点i匹配的点 ********************************************************************************/ const int MAXN = 120+5; int N, M; int g[MAXN][MAXN*2]; bool used[MAXN*2]; int pre[MAXN*2]; //深搜找交错路径 bool dfs(int t) { int i, tmp; for(i = N+1; i <= 2*N; i++) if(g[t][i] && !used[i]) { used[i] = true; if(pre[i]== -1 || dfs(pre[i])) { pre[i] = t; return true; } } return false; } int Match() { int i, j; int ans = 0; memset(pre, -1, sizeof(pre)); //贪心初始流,但是ms没有什么效果 for(i = 1; i <= n; i++) { for(j = n+1; j <= n+m; j++) if(g[i][j] && pre[j] == -1) { pre[j] = i; ans++; break; } if(j == n+m+1) { memset(used, 0, sizeof(used)); if(dfs(i)) ans++; } } return ans; } int main() { int i, u, v, T; scanf("%d", &T); while(T--) { scanf("%d %d", &N, &M); memset(g, 0, sizeof(g)); for(i = 0; i < M; i++) { scanf("%d %d", &u, &v); g[u][v+N] = 1; } printf("%d/n", N-Match()); } return 0; }

你可能感兴趣的:(图论)