Simple Path ZOJ - 3583--并查集

题目

A path with no repeated vertices of an undirected graph is called a simple path. Given an undirected graph and two verteices S and D, return the number of vertics which don't lie on any simple paths between S and D.

Input

The input contains multiple test cases.

Each case starts with a line of four integers, N(1 < N ≤ 100), M(1 ≤ M ≤ N(N - 1) / 2), S(0 ≤ S < N), D(0 ≤ D < N). N is the number of vertices, M is the number of edges, S and D are two different vertices. Then M lines follow, each line contains two different integers A(0 ≤ A < N) and B(0 ≤ B < N), which represents an edge of the graph. It's ensure that there is at least one simple path between S and D.

Output

Output the number of such vertics, one line per case.

Sample Input

4 3 0 2
0 1
1 2
1 3
4 4 0 2
0 1
1 2
1 3
2 3

Sample Output

1
0

题意

给你一个无向图,simple path的意思是一条没有重复点的路径,问你不在从 s 到 t 的所有简单路径的点有多少个。

分析

将0--(n-1),每个点都删除一次,如果在删除某个点的时候,有的点突然不与s或不与 t 相连了,那么这个点一定不是在simple path上的点。需要注意的是,在每次删点的时候,都需要重新建立并查集(除了那个被删的点)。还有就是要先用vis数组标记,不能直接计数,避免重复。

代码

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int N=105;
int pre[N];
bool vis[N];
int a[N*N],b[N*N];
int find(int x)
{
	int r=x;
	while(r!=pre[r])
		r=pre[r];
	int tmp,a=x;
	while(a!=r)
	{
		tmp=pre[a];
		pre[a]=r;
		a=tmp;
	}
	return r;
}
void unionn(int x,int y)
{
	int rx=find(x);
	int ry=find(y);
	if(rx!=ry)
		pre[ry]=rx;
}
int main()
{
	int n,m,s,t;
	while(~scanf("%d%d%d%d",&n,&m,&s,&t))
	{
		for(int i=0;i<m;i++)
			scanf("%d%d",&a[i],&b[i]);
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)//i表示每次删除的点  
		{
			for(int j=0;j<=n;j++)
				pre[j]=j;
			for(int j=0;j<m;j++)//每次删点之后,重新建立并查集  
			{
				if(a[j]!=i&&b[j]!=i)
					unionn(a[j],b[j]);
			}
			for(int j=0;j<n;j++)
			{
				if(j!=i&&find(j)!=find(s)&&find(j)!=find(t))
					vis[j]=1;	//标记  
			}
		}
		int ans=0;
		for(int i=0;i<n;i++)//计数  
		{
			if(vis[i])
				ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值