Antenna Placement(poj 3020)
原题链接
无向图的最小路径覆盖
无向图最小路径覆盖数=顶点数-二分图最大匹配数/2(理解不了这题,以后再来更新 )
Air Raid(poj 1422)
原题链接
题目类型:DAG的最小不相交路径覆盖
把原图的每个点V拆成Vx和Vy两个点,如果有一条有向边A->B,那么就加边Ax−>By。这样就得到了一个二分图。那么最小路径覆盖=原图的结点数-新图的最大匹配数。
需要说明的是,最小不相交性体现在对于二分图的匹配的求解上,匹配使得一个点的入度或者出度之多为1,从而避免了重复经过某点。
同时,关于该算法正确性的证明,可以这样理解,首先认为对于每个点都需要一条路径来走,那么应为N,在二分图的匹配问题求解过程中,每获得一个匹配,此时路径数减一,因此便有了最小路径覆盖的公式。
注意:若原图中的点的个数为N,那么新构建的二分图为NN,总结点数变为2N,但是不是2N * 2N
#include<iostream>
using namespace std;
#define NMAX 210
int Q, N, S;
int P[NMAX][NMAX];//代表的是拓展后的二分图
int v[NMAX];
int g[NMAX];
int find(int x) {
for (int i = 1; i <= N; i++) {
if (P[x][i] && !v[i]) {
v[i] = 1;
if (!g[i] || find(g[i])) {
g[i] = x;
return 1;
}
}
}
return 0;
}
int main() {
// cin >> Q;
scanf("%d", &Q);
while (Q--) {
//cin >> N >> S;
scanf("%d%d", &N,&S);
memset(P, 0, sizeof(P));
memset(g, 0, sizeof(g));
for (int i = 0; i < S; i++) {
int s, e;
//cin >> s >> e;
scanf("%d%d", &s, &e);
P[s][e] = 1;
}
//匈牙利算法
int res = 0;
for (int i = 1; i <=N; i++) {
memset(v, 0, sizeof(v));
if (find(i)) res++;
}
//cout << N - res << endl;
printf("%d\n", N - res);
}
}
tip:
1.memset(P, 0, sizeof§);写成了memset(P, 0, sizeof(Q));导致程序调试了好久,所以说,最好不要犯这些小错误,否则会酿成大错;如果犯了这些错误,请务必静下心来慢慢找。
Treasure Exploration(poj 2594)
原题链接
题目类型:DAG的最小可相交路径覆盖
先用floyd求出原图的传递闭包(注意传递闭包的三层循环是有顺序的要求的),即如果a到b有路径,那么就加边a->b。然后就转化成了最小不相交路径覆盖问题。
#include<iostream>
using namespace std;
#define NMAX 510
int Q, N, M;
int P[NMAX][NMAX];//代表的是拓展后的二分图
int v[NMAX];
int g[NMAX];
int find(int x) {
for (int i = 1; i <= N; i++) {
if (P[x][i] && !v[i]) {
v[i] = 1;
if (!g[i] || find(g[i])) {
g[i] = x;
return 1;
}
}
}
return 0;
}
void floyd() {
for (int k = 1; k <= N; ++k)
for (int i = 1; i <= N; ++i)
for (int j = 1; j <= N; ++j)
if (P[i][k] && P[k][j])//传递可达性
P[i][j] = 1;
}
int main() {
while (1) {
cin >> N >> M;
if (!N && !M) return 0;
memset(P, 0, sizeof(P));
memset(g, 0, sizeof(g));
for (int i = 0; i < M; i++) {
int s, e;
cin >> s >> e;
P[s][e] = 1;
}
floyd();
//匈牙利算法
int res = 0;
for (int i = 1; i <=N; i++) {
memset(v, 0, sizeof(v));
if (find(i)) res++;
}
//cout << N - res << endl;
printf("%d\n", N - res);
}
}
参考链接:有向图最小路径覆盖
floyd传递闭包的计算
这篇博客探讨了如何利用图论中的最小路径覆盖问题解决AirRaid和TreasureExploration等题目。通过将原图转化为二分图,并应用匈牙利算法求解最大匹配,得出最小路径覆盖的数量。Floyd算法用于构造传递闭包,转换问题为最小不相交路径覆盖。博客还提醒读者注意编程细节,如避免memset的小错误,确保程序的正确性。
243

被折叠的 条评论
为什么被折叠?



