您的位置:首页 > 编程语言 > Go语言

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: