zoj3583Simple Path【并查集(思想很好)】
大意:
告诉你一个无向图
然后定义一个simple path是一条路径上面不包含重复的点
然后告诉你两个点s, t
问有多上个点是不在s到t的simple路径上
分析:
对于从s到t的simple path上 无论删除其他的任何一个 点 那么这个点一定是要么和s相连,要么和t相连
从这个角度出发的话
如果删除任何一点
如果有个点突然不和s,或t相连了
那么改点也就一定不是该simple path上的点
最后统计一下个数即可
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 105; 7 int a[maxn * maxn], b[maxn * maxn]; 8 int vis[maxn]; 9 int fa[maxn]; 10 11 int Find(int i) { 12 if(fa[i] == i) return i; 13 return fa[i] = Find(fa[i]); 14 } 15 16 void Union(int u, int v) { 17 int fu = Find(u); int fv = Find(v); 18 if(fu != fv) { 19 fa[fu] = fv; 20 } 21 } 22 23 int main() { 24 int n, m, s, t; 25 while(EOF != scanf("%d %d %d %d",&n, &m, &s, &t) ) { 26 for(int i = 1; i <= m; i++) { 27 scanf("%d %d",&a[i], &b[i]); 28 } 29 memset(vis,0, sizeof(vis)); 30 for(int i = 0; i < n; i++) { 31 for(int j = 0; j <= n; j++) fa[j] = j; 32 for(int j = 1; j <= m; j++) { 33 if(a[j] != i && b[j] != i) { 34 Union(a[j], b[j]); 35 } 36 } 37 for(int j = 0; j < n; j++) { 38 if(j != i && Find(j) != Find(s) && Find(j) != Find(t)) { 39 vis[j] = 1; 40 } 41 } 42 } 43 int ans = 0; 44 for(int i = 0; i < n; i++) { 45 if(vis[i]) { 46 ans++; 47 } 48 } 49 printf("%d\n",ans); 50 } 51 return 0; 52 }