比赛总结
题目
题意:
一个无向图,每次查询两个点s和t,判断是否s到t间存在且只存在一条简单路径。
题解:
若只存在一条简单路径,那么删掉路径上任意一条边,s和t 都变得不可达,也就是说路径上的边都是桥边。那么如果删掉所有非桥边,符合条件的点对就必须在同一个连通分量里。
//Time:126ms //Memory:1775B #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> const int MAXN = 200010; using namespace std; bool ty[MAXN]; int he[MAXN],to[MAXN],nex[MAXN],top,bel[MAXN],now,btop; int dfn[MAXN],low[MAXN]; void add(int u,int v) { to[top]=v; nex[top]=he[u]; he[u]=top++; } void tarjan(int h,int pre) { dfn[h]=low[h]=++now; for(int i=he[h];i!=-1;i=nex[i]) if((i^1)!=pre) { if(!dfn[to[i]]) { tarjan(to[i],i); low[h]=min(low[to[i]],low[h]); if(dfn[h]<low[to[i]]) ty[i]=ty[i^1]=1; } else low[h]=min(low[h],dfn[to[i]]); } } void bfs(int h) { queue<int> que; que.push(h); ++btop; bel[h]=btop; while(que.size()) { h=que.front(); que.pop(); for(int i=he[h];i!=-1;i=nex[i]) if(ty[i]&&!bel[to[i]]) bel[to[i]]=btop,que.push(to[i]); } } int main() { //freopen("/home/moor/Code/input","r",stdin); int n,m,q; while(scanf("%d%d%d",&n,&m,&q)&&n&&m&&q) { int u,v; top=0; btop=1; now=1; memset(dfn,0,sizeof(dfn)); memset(bel,0,sizeof(bel)); memset(ty,0,sizeof(ty)); memset(he,-1,sizeof(he)); for(int i=0;i<m;++i) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i,-1); for(int i=1;i<=n;++i) if(!bel[i]) bfs(i); for(int i=0;i<q;++i) { scanf("%d%d",&u,&v); printf("%c\n",bel[u]==bel[v]?'Y':'N'); } printf("-\n"); } return 0; }