Div1 小A抓小B tarjan双连通分量缩点+dfs

来源:互联网 发布:编程 网页开发 编辑:程序博客网 时间:2024/06/06 07:42

题目描述

A和小B在一个无向图G上进行一个游戏。图G是连通的,有n个点,n条边,无重边,无自环,结点编号为1~n。游戏开始前小A在结点x,小B在结点yxy)。游戏开始后,小A和小B轮流进行移动(小A先移动),每次移动可以从当前结点移动到与当前结点相邻的某个结点。小A的目标是抓到小B(某一次移动之后小A与小B在同一个结点),小B的目标是不被小A抓到。两人都有图G的地图,并且知道对方在哪个结点,两人都采取最优策略,问小A是否能通过有限次移动抓到小B。

输入描述

第1行3个整数n、x、y

第2~n+1行每行2个整数u、v,代表u与v之间有边相连。

输出描述

若小A能通过有限次移动抓到小B,输出1,否则输出0。

数据范围

n≤100000

样例输入

10 2 41 21 32 41 55 61 75 86 93 108 10

样例输出

1

题解,这是一个树,并且这个树上存在且存在一个环。

1.当A和B之间距离为1或0的时候,直接输出1。

2.否则的话,当环的长度小于等于3的时候,直接输出1,因为B一定会被A捉到。

3.我们进行双连通分量的缩点,将环缩成一个点,下面我们判断,当A、B同属于一个环上的时候,直接输出0,因为B绕着环跑永远不会被捉到。

4.然后我们从环缩成的点开始进行dfs序遍历,得到每一个点到基环的距离,如果dis[belong[x]] + 1 <= dis[belong[y]]表明A距离基环更近,直接输出1,否则输出0.

代码:

#include <bits/stdc++.h>using namespace std;const int MAXN = 1e5+10;int head[MAXN];int cnt;struct edge{     int v;     int next;     int cost; }Es[MAXN<<1];  void init(){     cnt = 0;     memset(head,-1,sizeof(head)); }inline void add_edge(int i,int j,int cost){       Es[cnt].v = j;     Es[cnt].cost = cost;     Es[cnt].next = head[i];     head[i] = cnt++; }   int n,x,y;int DFN[MAXN],LOW[MAXN];int stk[MAXN],vis[MAXN],belong[MAXN];int idx,sccnum,tot;vector<int> scc[MAXN];void tarjan(int x,int fa){DFN[x] = LOW[x] = ++ tot;stk[++idx] = x;vis[x] = 1;for(int e = head[x];e != -1;e = Es[e].next){int v = Es[e].v;if(v == fa) continue;if(!DFN[v]){tarjan(v,x);LOW[x] = min(LOW[x],LOW[v]);}else if(vis[v]){LOW[x] = min(LOW[x],DFN[v]);}}if(DFN[x] == LOW[x]){++sccnum;int item;do{item = stk[idx--];belong[item] = sccnum;scc[sccnum].push_back(item);vis[item] = 0;}while(x != item);}}int dis[MAXN];int vis2[MAXN];void dfs(int x,int dep){dis[x] = dep;for(int i  = 0;i < scc[x].size();++i){int u = scc[x][i];for(int e = head[u];e != -1;e = Es[e].next){int v = Es[e].v;if(!vis2[belong[v]]){vis2[belong[v]] = 1;dfs(belong[v],dep+1);}}}}int main(){init();scanf("%d%d%d",&n,&x,&y);if(x == y) {puts("1");return 0;}for(int i = 0;i < n;i++){int a,b;scanf("%d%d",&a,&b);add_edge(a,b,1);add_edge(b,a,1);}for(int e = head[x];e != -1;e = Es[e].next){int v = Es[e].v;if(v == y){puts("1");return 0;}}tarjan(1,0);int start = 0;for(int i = 1;i <= sccnum;i++){ if(scc[i].size() > 3){ start = i; }}if(!start){puts("1");return 0;}if(belong[x] == belong[y]){puts("0");return 0;}dfs(start,0);if(dis[belong[x]] + 1 <= dis[belong[y]]){puts("1");}else{puts("0");}return 0;}/*7 4 11 22 33 44 55 66 77 4*/


原创粉丝点击