POJ 2762 Going from u to v or from v to u?
来源:互联网 发布:php 打开文件过程 编辑:程序博客网 时间:2024/06/03 16:57
Description
Input
The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.
Output
Sample Input
13 31 22 33 1
Sample Output
Yes
题目描述
给一个有向图,有 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”。
这就不是裸的强连通分量了,刚做这道题不知道怎么处理,后来在网上看到了别人的思路才弄懂,感觉挺巧妙。
思考一下,对于一个有向图而言,里面的强连通分量肯定满足题目的条件,因为强连通分量内是u可到v,而且,v可到u,所以我们第一步工作就是强连通分量缩点,变为一个DAG(即:有向无环图,Directed Acyclic Graph)。对于这个DAG里面的任意两个点U,V,如果满足题目的条件,那么点U,V里面包含的原图的点也肯定是满足的所以问题转化为怎么判断这个DAG是满足题目条件呢?其实判断很简单,就是看这个DAG里面有多少个点的入度为0,多少个点出度为0。
如果DAG中,有2个或2个以上的点的入度为0,那么这个DAG就是No,因为这说明有两个点是无法“进去”的,没有点能“进去”U,也没有点能“进去”V,那么这两个点肯定互相不能“进去”,即到达如果DAG中,有2个或2个以上的点的出度为0,那么这个DAG就是No,因为说明这两个点是无法“出去的”。
反证法,点U和V,它们出度都是0,假设它们满足题目条件,从U能到V,或者从V能到U。
1.因为点U出度为0,所以无法“出去”,它肯定无法到达V。
2.因为点V出度为0,所以无法“出去”,它肯定无法到达U。
3.综上,点U无法到达V,点V无法到达点U,与假设矛盾,所以与题目不成立。
那么什么最后一个问题,如果这个DAG,入度为0的点的个数 <= 1 , 出度为0的点的个数 <= 1 , 它就一定Yes吗?
这个就比较容易想了,首先,1个DAG中,不可能所有点都有入度,即入度为0的点个数为0,是不可能发生的。同样的,可能所有点都有出度,即出度为0的点个数为0,是不可能发生的。
那剩下的情况就是,1个点入度为0为u,1个点出度为0为v。这个图,呈现一个“橄榄形”。如果从点u走到点v,能经过所有的点,那么就是Yes,否则是No。因为无法经过所有的点的话,说明图中出现了“分叉”,这种“分叉”必定导致两个点互相不可达。而从u到v,经过所有点,其实就是把这个DAG变成了一条链,就是判断这个DAG是否存在一条链贯穿所有点。
怎么判断链呢?可以转化为拓扑排序,或者DP最长路,在这里就只说拓扑排序。
拓扑:拓扑排序可能有多种结果,但是如果是一个最长链,结果则是唯一的,结果要唯一,其实就是从初始化开始,到后面的任何一次删弧入队操作,都是保证了每次都只有一个元素入队,即永远只有一个元素的入度为0,如果中途有一次出现了有两个点入度为0,那么其实代表出现了一种“分叉”。
而且拓扑排序可以综合掉前面的情况,不需要特判DAG有几个点入度为0,出度为0,直接拓扑,在拓扑过程就已经判断了
下面是代码:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <cmath>#include <cctype>#include <ctime>#include <queue>using namespace std;int n,m,t,index,top,s,sum;int first[10001],father[10001],zhan[10001];int low[10001],num[10001];bool dian[10001];struct tarjan{int x,y,next;};tarjan bian[100001];int topzhan[10001],r[10001],a[1001][1001];void clean(){ index=0; top=0; s=0; sum=0; memset(first,-1,sizeof(first)); memset(father,0,sizeof(father)); memset(zhan,0,sizeof(zhan)); memset(low,0,sizeof(low)); memset(num,0,sizeof(num)); memset(dian,false,sizeof(dian)); memset(bian,0,sizeof(bian)); memset(topzhan,0,sizeof(topzhan)); memset(r,0,sizeof(r)); memset(a,0,sizeof(a));}void build(int x,int y){ s++; bian[s].next=first[x]; first[x]=s; bian[s].x=x; bian[s].y=y;}void dfs(int x) //Tarjan{ index++; low[x]=index; num[x]=index; top++; zhan[top]=x; dian[x]=true; int i,k; k=first[x]; while(k!=-1) { if(num[bian[k].y]==0) { dfs(bian[k].y); low[x]=min(low[x],low[bian[k].y]); } else if(dian[bian[k].y]) low[x]=min(low[x],num[bian[k].y]); k=bian[k].next; } if(low[x]==num[x]) { sum++; i=zhan[top]; while(i!=x) { father[i]=sum; dian[i]=false; top--; i=zhan[top]; } father[i]=sum; dian[i]=false; top--; }}int topsort() //拓扑排序 { int tot=0,number=0; for(int i=1;i<=sum;i++) if(r[i]==0) {number++; tot++; topzhan[tot]=i;} if(number>1) return 0; //有两个或两个以上入度为0的点 number=0; while(tot>0) { int u=topzhan[tot]; tot--; for(int i=1;i<=a[u][0];i++) { r[a[u][i]]--; if(r[a[u][i]]==0) {number++; tot++; topzhan[tot]=a[u][i];} } if(number>1) return 0; //删弧后,同时出现了两个点入度为0 number=0; } return 1;}int main(){ //freopen("lx.in","r",stdin); //freopen("lx.out","w",stdout); scanf("%d",&t); for(int i=1;i<=t;i++) { clean(); scanf("%d%d",&n,&m); for(int j=1;j<=m;j++) { int x,y; scanf("%d%d",&x,&y); build(x,y); } for(int j=1;j<=n;j++) if(num[j]==0) dfs(j); for(int j=1;j<=n;j++) for(int k=first[j];k!=-1;k=bian[k].next) { int u,v; u=father[j]; v=father[bian[k].y]; if(u!=v) {r[v]++; a[u][0]++; a[u][a[u][0]]=v;} //重新建图 } int ans=topsort(); if(ans) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0;}
- POJ 2762 Going from u to v or from v to u? (Tarjan) - from lanshui_Yang
- 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?
- 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?
- 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?
- 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 (Kosaraju+缩点+单链图)
- 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? 强连通+判断链
- 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)
- apache 反向代理配置
- Plsql连接64位oracle
- 数据库连接
- mysql 同一IP 产生太多终端的数据库连接导致阻塞
- JDBC代码示例
- POJ 2762 Going from u to v or from v to u?
- 赛码网-基本算法-1.股神
- maven 问题解决 tools以及jconsole两个jar包 无效
- H5的FormData对象完成ajax上传文件multiFile
- Spring @Scheduled应用解析
- linux 常用操作指令(随时更新)
- 迟到的Volley源码解析
- Java学习日志 17.04.27 浅谈Java运行机制
- 市场占有率第一 中企动力领跑企业网站服务市场