[Tyvj1922]Freda的迷宫

Freda的迷宫

题解

我们要使u与v之间有且只有一条简单路径,就是让这两个点必须联通,而且路径上没有环。

那么,就成了找桥,因为要保证两端的简单路径有且只有一条,就必须在由桥连成的路径两端。

我们便先用tarjan把所有的桥给跑出来,将桥边记录下来。

再用并查集来维护连接。因为将桥挑出来后所有的桥一定会形成一片森林,只要不在这片森林的同一棵树上则一定不是有且只有一条简单路径。

具体实现过程就很简单了。

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define MAXM 100005
#define MAXN 10005
typedef long long LL;
#define gc() getchar()
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=gc();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
	while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
	x*=f;
}
int from[MAXM<<1],to[MAXM<<1],nxt[MAXM<<1];
int head[MAXN],tot,cnt,fa[MAXN];
int dfn[MAXN],low[MAXN];
int n,m,q;
void addEdge(int u,int v){
	from[++tot]=u;to[tot]=v;
	nxt[tot]=head[u];head[u]=tot;
}
void makeSet(int x){
	for(int i=1;i<=x;i++)fa[i]=i;
} 
int findSet(int x){
	if(x!=fa[x])fa[x]=findSet(fa[x]);
	return fa[x];
}
void unionSet(int a,int b){
	int u=findSet(a),v=findSet(b);
	if(u!=v)fa[u]=v;
}
void tarjan(int u,int f){
	dfn[u]=low[u]=++cnt;
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];//printf("%d-->%d\n",u,v);
		if(v==f)continue;
		if(!dfn[v]){
			tarjan(v,u);low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u])unionSet(u,v);
		}
		else if(dfn[v]<dfn[u])
			low[u]=min(low[u],dfn[v]);
	}
	//printf("%d:%d %d\n",u,dfn[u],low[u]);
}
signed main(){
	read(n);read(m);read(q);
	for(int i=1;i<=m;i++){
		int x,y;read(x);read(y);
		addEdge(x,y);addEdge(y,x);
	}
	makeSet(n);tarjan(1,0);
	for(int i=1;i<=q;i++){
		int u,v;read(u);read(v);
		int uu=findSet(u),vv=findSet(v);
		puts(uu==vv?"Y":"N"); 
	}
	return 0;
}

谢谢

发布了117 篇原创文章 · 获赞 154 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Tan_tan_tann/article/details/104627585
今日推荐