[练习][poj2762]tarjan缩点 Going from u to v or from v to u?
2017-10-30 17:20
375 查看
题目背景
poj2762
题目描述
In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn’t know how to decide if a task is possible. To make her life easier, Jia
11a4c
jia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
题目大意
给一个有向图,有 n 个点,m 条有向边。对于图中任意两个点 u,v ,如果从 u 能到 v ,或者 从 v 能到 u ,则称这对顶点是可行的,如果图中任意一对顶点都是可行的,可以输出“Yes”,否则输出“No”。
注意,这里是 u 到达 v ,或者 v 到达 u ,是“或者”不是“而且”!
输入格式
输入第一行为一个整数 T , 表示数据组数。
每组数据第一行为两个整数 n 和 m(0<n<1001;m<6000),分别表示点和边的数量。
接下来有 m 行,每行两个整数 u 和 v ,表示从 u 到 v 有一条有向边相连。
输出格式
如果图中任意一对顶点都是可行的,可以输出“Yes”,否则输出“No”。
样例数据
输入
1
3 3
1 2
2 3
3 1
输出
Yes
分析:这个题在一个强联通分量里的就不必说了,所以要考虑不在同一个强联通分量里的点。缩点之后,要想任意两个点都能“连通”,就需要整个图是一条链(因为缩完点后的图就已经没有强联通分量了,要想任意两点“连通”就不能出现分叉,不然分叉之间就没法连通了)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/73410465878cdab3ea0c5ba4e5b7fae7)
(一条链两两都“连通”)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/b90035aa86f662b2ebe0a055684f40b1)
(分叉部分没法“连通”)
所以说怎么求是一条链呢,只需要找到入度为0的点(也就是链端),dfs之后看最深的deep是不是正好是缩完点后的点的数量就可以了。
代码
本题结。
poj2762
题目描述
In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn’t know how to decide if a task is possible. To make her life easier, Jia
11a4c
jia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
题目大意
给一个有向图,有 n 个点,m 条有向边。对于图中任意两个点 u,v ,如果从 u 能到 v ,或者 从 v 能到 u ,则称这对顶点是可行的,如果图中任意一对顶点都是可行的,可以输出“Yes”,否则输出“No”。
注意,这里是 u 到达 v ,或者 v 到达 u ,是“或者”不是“而且”!
输入格式
输入第一行为一个整数 T , 表示数据组数。
每组数据第一行为两个整数 n 和 m(0<n<1001;m<6000),分别表示点和边的数量。
接下来有 m 行,每行两个整数 u 和 v ,表示从 u 到 v 有一条有向边相连。
输出格式
如果图中任意一对顶点都是可行的,可以输出“Yes”,否则输出“No”。
样例数据
输入
1
3 3
1 2
2 3
3 1
输出
Yes
分析:这个题在一个强联通分量里的就不必说了,所以要考虑不在同一个强联通分量里的点。缩点之后,要想任意两个点都能“连通”,就需要整个图是一条链(因为缩完点后的图就已经没有强联通分量了,要想任意两点“连通”就不能出现分叉,不然分叉之间就没法连通了)
(一条链两两都“连通”)
(分叉部分没法“连通”)
所以说怎么求是一条链呢,只需要找到入度为0的点(也就是链端),dfs之后看最深的deep是不是正好是缩完点后的点的数量就可以了。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> #include<queue> #include<set> using namespace std; int getint() { int sum=0,f=1; char ch; for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar()); if(ch=='-') { f=-1; ch=getchar(); } for(;isdigit(ch);ch=getchar()) sum=(sum<<3)+(sum<<1)+ch-48; return sum*f; } int T,n,m; int tot,first[1010],nxt[12010],to[12010]; int dep,dfn[1010],low[1010],top,zhan[1010],cnt,qlt[1010]; bool ruzhan[1010]; int rudu[1010]; int dis[1010],ans; bool visit[1010]; void add(int x,int y) { tot++; nxt[tot]=first[x]; first[x]=tot; to[tot]=y; } void tarjan(int u) { dep++; dfn[u]=dep; low[u]=dep; ruzhan[u]=true; zhan[top]=u; top++; for(int p=first[u];p;p=nxt[p]) { int v=to[p]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(ruzhan[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { cnt++; while(zhan[top]!=u) { top--; ruzhan[zhan[top]]=false; qlt[zhan[top]]=cnt; } } } void dfs(int u) { ans=max(dis[u],ans);//找到最深deep for(int p=first[u];p;p=nxt[p]) { int v=to[p]; if(!visit[v]) { visit[v]=true; if(qlt[v]!=qlt[u]) dis[v]=dis[u]+1;//不是同一个强联通分量,deep++ else dis[v]=dis[u];//是同一个,deep不变 dfs(v); } } } int main() { freopen("uv.in","r",stdin); freopen("uv.out","w",stdout); T=getint(); while(T--) { memset(first,0,sizeof(first));//清零操作 memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(rudu,0,sizeof(rudu)); memset(visit,0,sizeof(visit)); tot=0,dep=0,cnt=0,ans=0; int x,y; n=getint(),m=getint(); for(int i=1;i<=m;++i) { x=getint(),y=getint(); add(x,y); } for(int i=1;i<=n;++i)//tarjan缩点 if(!dfn[i]) tarjan(i); for(int i=1;i<=n;++i)//给每个强联通分量求入度 for(int p=first[i];p;p=nxt[p]) { int v=to[p]; if(qlt[i]!=qlt[v]) rudu[qlt[v]]++; } for(int i=1;i<=n;++i)//在入度为0的点开始dfs if(rudu[qlt[i]]==0) { dis[i]=1; visit[i]=true; dfs(i); break;//因为链只有一个入度为0的点,所以只要找到一个算完就可以break掉了, //如果还有入度为0的点就说明本来就不是链,不需要再dfs, //因为本题不知道T的大小,所以不break看似n方也可能过不了,反正我把所有入度为0的点都dfs就TLE了 } if(ans==cnt)//数量相等,说明是链 cout<<"Yes"<<'\n'; else cout<<"No"<<'\n'; } return 0; }
本题结。
相关文章推荐
- POJ 2762 Going from u to v or from v to u? Tarjan缩点+判断链
- poj 2762 Going from u to v or from v to u? 【判断图是否为弱连通】 【tarjan求SCC + 缩点 + 拓扑排序】
- POJ - 2762 Going from u to v or from v to u? (Tarjan 缩点)
- POJ2762 Going from u to v or from v to u? 强连通 Tarjan缩点+拓扑排序topsort
- poj 2762 Going from u to v or from v to u?(强连通、缩点、拓扑)
- POJ 2762 Going from u to v or from v to u? 缩点
- POJ-2762 Going from u to v or from v to u? (强连通分量[Tarjan]&&(拓扑排序||树形DP))
- POJ 2762【强联通缩点】【拓扑排序】Going from u to v or from v to u?
- 【POJ 2762】Going from u to v or from u ? (Tarjan + 拓扑排序)
- POJ 2762 Going from u to v or from v to u?(Tarjan + 拓扑排序)
- POJ 2762 Going from u to v or from v to u? (Tarjan) - from lanshui_Yang
- Going from u to v or from v to u? - POJ 2762 Tarjan+拓扑排序
- POJ 2762 Going from u to v or from v to u? (Tarjan) - from lanshui_Yang
- [ tarjan + dfs ] poj 2762 Going from u to v or from v to u?
- POJ 2762 Going from u to v or from v to u?(Tarjan)
- [ tarjan + dfs ] poj 2762 Going from u to v or from v to u?
- poj 2762 Going from u to v or from v to u?(缩点+拓扑排序)
- poj2762 Going from u to v or from v to u? --- 缩点+拓扑
- poj 2762 Going from u to v or v to u (tarjan+缩点+dfs搜索)
- POJ 2762 Going from u to v or from v to u? (图论-tarjan)