ZOJ-3583 Simple Path
这个题是syg老师上课提到的,我感觉还挺有意思的,课下找来做做
本题所用性质:
想象一下从 s s s到 t t t的一条简单路,简单路上的点 i i i,不管删去图上任何一个点,点 i i i总会至少与 s s s或 t t t在一个相连的集合中
不在简单路上的点 j j j,一定可以找到一个点 d d d并删去,使得 j j j与 s s s和 t t t都不在一个相连的集合中
上课已经进行证明
本题可以利用并查集解决
#include<iostream>
#include <cstring>
using namespace std;
int n, m, s, t;
const int Max_size = 1e2 + 20;
bool g[Max_size][Max_size];
int p[Max_size]; // 并查集
bool flag[Max_size]; //是否在简单路径上
void init_() {
for (int i = 0; i < Max_size; i++)
p[i] = i;
}
int find_(int x) {
if (x != p[x])p[x] = find_(p[x]);
return p[x];
}
void union_(int x, int y) {
x = find_(x);
y = find_(y);
p[x] = y;
}
int main() {
while (cin >> n >> m >> s >> t) {
memset(g, 0, sizeof(g));
memset(flag, 0, sizeof(flag));
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b;
g[a][b] = g[b][a] = true;
}
for (int i = 0; i < n; i++) {
init_();
// 选择要删除的顶点
for (int j = 0; j < n; j++) {
for (int k = j + 1; k < n; k++) {
// 遍历上三角矩阵
if (j != i && k != i && g[j][k]) {
union_(j, k);
}
}
}
for (int j = 0; j < n; j++) {
// 根据性质逐个判断每一个顶点
if (find_(s) != find_(j) && find_(t) != find_(j) && j != i) {
flag[j] = true;
}
}
}
int ans = 0;
for (int i = 0; i < n; i++)
if (flag[i])ans++;
cout << ans << "\n";
}
return 0;
}

1194

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



