poj 2762

http://poj.org/problem?id=2762

题意:给一个无向图,问对任意的两个点x,y,是否都存在一条路径从一个点出发到达另一个点。

思路:先用tarjan对无向图进行缩边和求弱连通分量,如果弱连通分量不为1,则No;然后重建无向图,判断是否是线树,是则Yes,否则No。

注意:缩边后的图不一定是棵标准的树。

View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<stack>
#include<utility>
#include<vector>
using namespace std;

const int maxn = 1005;

struct nd
{
        int from,to,next;
}edge[maxn*6];

int head[maxn],ecnt,idx,cnt;
int vis[maxn],dfn[maxn],low[maxn];
int dgr[maxn],belong[maxn];
stack<int>st;

void add(int s,int t)
{
        edge[ecnt].from = s;
        edge[ecnt].to = t;
        edge[ecnt].next = head[s];
        head[s] = ecnt++;
}

void tarjan(int u)
{
        int i,v;
        dfn[u] = low[u] = ++idx;
        vis[u] = 1;
        st.push(u);
        for(i = head[u]; i != -1; i = edge[i].next)
        {
                v = edge[i].to;
                if(!dfn[v]){
                        tarjan(v);
                        low[u] = min(low[v],low[u]);
                }else if(vis[v]) low[u] = min(dfn[v],low[u]);
        }
        if(dfn[u] == low[u])
        {
                cnt++;
                do{
                        v = st.top();
                        st.pop();
                        vis[v] = 0;
                        belong[v] = cnt;
                }while(v!=u);
        }
}
int dfs(int cur)
{
        int i,j,k = 0,v;
        for(i = head[cur]; i != -1; i = edge[i].next)
        {
                j = edge[i].to;
                dgr[j]--;
                if(!dgr[j]){k++; v = j;}
                if(k>1)return 1;
        }
        if(k) return dfs(v);
        return 0;
}

int main()
{
        int i,j,k,t,n,m,u,v;
        scanf("%d",&t);
        while(t--)
        {
                scanf("%d %d",&n,&m);
                memset(belong,0,sizeof(belong));
                memset(head,-1,sizeof(head));
                memset(dgr,0,sizeof(dgr));
                memset(vis,0,sizeof(vis));
                memset(dfn,0,sizeof(dfn));
                ecnt = 0; idx = 0; cnt = 0;
                for(i = 0; i < m; ++ i)
                {
                        scanf("%d %d",&u,&v);
                        add(u,v);
                }
                for(i = 1; i <= n; ++ i) if(!dfn[i])tarjan(i);
                k = ecnt; ecnt = 0;
                memset(head,-1,sizeof(head));
                for(i = 0; i < k; ++ i)
                {
                        u = belong[edge[i].from];
                        v = belong[edge[i].to];
                        if(u!=v){ add(u,v);  dgr[v]++; }
                }
                k = 0;
                for(i = 1; i <= cnt; ++ i) if(!dgr[i]){k++;j = i;}
                if(k!=1){puts("No"); continue;}
                k = dfs(j);
                if(!k)puts("Yes");else puts("No");
        }
        return 0;
}

posted on 2012-06-27 19:09  aigoruan  阅读(137)  评论(0)    收藏  举报

导航