poj 2762 Going from u to v or from v to u?
2013-07-22 16:07
337 查看
题目描述: 为了让他们的儿子变得更勇敢些,Jiajia和Wind将他们带到一个大洞穴中。洞穴中有n个房 间,有一些单向的通道连接某些房间。每次,Wind选择两个房间x和y,要求他们的一个儿子从 一个房间走到另一个房间,这个儿子可以从x走到y,也可以从y走到x。Wind保证她布置的任 务是可以完成的,但她确实不知道如何判断一个任务是否可以完成。为了使Wind下达任务更容 易些,Jiajia决定找这样的一个洞穴,每对房间(设为x和y)都是相通(可以从x走到y,或者 可以从y走到x)的。给定一个洞穴,你能告诉Jiajia,Wind是否可以任意选择两个房间而不用 担心这两个房间可能不相通吗? // 求解的是单连通性,但首先要转换成强连通分量的求解。这是因为,强连通分量中 的顶点间存在双向的路径,因此可以将每个强连通分量收缩成一个新的顶点。在有向图的处理中 经常需要将强连通分量收缩成一个顶点。 强连通分量收缩后,再求其拓扑排序。假设求得的拓扑序存储在topo[MAX]中,topo[i]与 topo[i+1]存在边连通(i 到i+1 或i+1 到i),则定有i 到i+1 的边。而如果每个topo[i]与topo[i+1] 都存在边连通(即有i 到i+1 的边)时,topo[i]到任意topo[j]便都有边连通。 // topsort时偷懒 用了邻接矩阵 复杂度成了 n^2 写成邻接表应该要快好多 #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <string.h> using namespace std; #define MOD 1000000007 #define maxn 6100 #define maxm 1010 struct Edge{ int to; int next; Edge(){}; Edge(int u,int v){to=u;next=v;} }E[maxn]; stack<int> S; int V[maxm],num; int belong[maxm]; int pre[maxm]; int dfst,scc; int ans; bool G[maxm][maxm]; int in[maxm]; void init(int n){ dfst=scc=0; num=0; ans=0; while(!S.empty()) S.pop(); for(int i=1;i<=n;i++){ V[i]=-1; pre[i]=0; belong[i]=0; } } void add(int u,int v){ E[num].to=v; E[num].next=V[u]; V[u]=num++; } int tarjan(int u){ int lowu=pre[u]=++dfst; int v,e; S.push(u); for(e=V[u];e!=-1;e=E[e].next){ v=E[e].to; if(!pre[v]){ int lowv=tarjan(v); lowu=min(lowu,lowv); } else if(!belong[v]) lowu=min(lowu,pre[v]); } if(lowu==pre[u]){ scc++; for(;;){ int x=S.top();S.pop(); belong[x]=scc; if(x==u) break; } } return lowu; } int top[maxm],tn; void topsort(){ int i,j,k; tn=0; bool vi[maxm]={0}; while(1){ for(i=1;i<=scc;i++) if(!in[i]&&!vi[i]) break; vi[i]=true; // printf("%d ",i); if(i>scc) break; top[tn++]=i; for(j=1;j<=scc;j++) if(G[i][j]) in[j]--; } } int main() { int n,m,T; int u,v; int i,j=1; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); init(n); for(i=1;i<=m;i++){ scanf("%d %d",&u,&v); add(u,v); } for(i=1;i<=n;i++) if(!pre[i]) tarjan(i); // for(i=1;i<=n;i++) printf("%d ",belong[i]); for(i=1;i<=scc;in[i]=0,i++) for(j=1;j<=scc;j++) G[i][j]=0; int e,u,v; for(i=1;i<=n;i++) { for(e=V[i];e!=-1;e=E[e].next){ u=belong[i]; v=belong[E[e].to]; if(u!=v){ G[u][v]=1; in[v]++; // printf("%d ",v); } } } topsort();//printf("\\"); int flag=1; for(i=1;i<tn;i++) if(!G[top[i-1]][top[i]]){ flag=0;break; } if(flag) printf("Yes\n"); else printf("No\n"); } return 0; }
相关文章推荐
- 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 ... 弱连通图 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?(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?
- POJ2762-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 ... 弱连通图 tarjan
- poj 2762 Going from u to v or from v to u 判断图中任意两点x,y是否总是存在x->y或者y->x
- POJ 2762 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? 强连通分量+DAG最长路
- POJ 2762 Going from u to v or from v to u?【强连通Kosaraju+拓扑排序】
- [ 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 (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? 双连通分量+拓扑排序