POJ 2762 Going from u to v or from v to u?

 

 POJ 2762 Going from u to v or from v to u?

 

题意:有n个山洞m条路,问任意两点x,y能否存在从x到y或者从y到x。

思路:

1、注意是或而不是和,所以“缩点”后,由于“缩点”内的点相互可达,所以不需要管“缩点”内的点。注意,不是判断强连通的数量为1,而是判断是否是弱连通。

2、如果两点不可达那么在拓扑排序时,该两点谁也不是谁的前驱和后继,所以在拓扑排序时只要同时出现至少两个入度为0的点,那么这些点一定互不可达,所以只要判断拓扑的方式是否唯一即可。

第一种方法:只要用拓扑判断入度为0的点是否为1个,如果有多个,就出现在分叉,不可能从x到y。

第二种方法:从入度为0的点DFS搜索最长能到达的路径如果路径长度等于点数,说明可以从源点访问完所有点。

 

知识充电: 

强连通图:在有向图中, 若对于每一对顶点v1和v2, 都存在一条从v1到v2和从v2到v1的路径,则称此图是强连通图.

弱连通图:将有向图的所有的有向边替换为无向边,所得到的图称为原图的基图。如果一个有向图的基图是连通图,则有向图是弱连通图。

单向连通图:如果有向图中,对于任意节点v1和v2,至少存在从v1到v2和从v2到v1的路径中的一条,则原图为单向连通图。

 

三者之间的关系是,强连通图必然是单向连通的,单向连通图必然是弱连通图。

CODE:

 

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
using  namespace std;

#define MAXN 50010
#define MAXM 100010

struct Edge
{
     int v, next;
}edge[MAXM], edge2[MAXM];

int first[MAXN], first2[MAXN],stack[MAXN], ins[MAXN], dfn[MAXN], low[MAXN];
int belong[MAXM];
int ind[MAXN], outd[MAXN], topo[MAXN];

int n, m;
int cnt, cnt2;
int scnt, top, tot;

void init()
{
    cnt =  0, cnt2 =  0;
    scnt = top = tot =  0;
    memset(dfn,  0sizeof(dfn));
    memset(first, - 1sizeof(first));
    memset(first2, - 1sizeof(first2));
    memset(ins,  0sizeof(ins));
    memset(ind,  0sizeof(ind));
     // memset(outd, 0, sizeof(outd));
    
// memset(topo, 0, sizeof(topo));
}

void read_graph( int u,  int v)
{
    edge[cnt].v = v;
    edge[cnt].next = first[u];
    first[u] = cnt++;
}

void read_graph2( int u,  int v)  // 重构图 
{
    edge2[cnt2].v = v;
    edge2[cnt2].next = first2[u], first2[u] = cnt2++;
}

void dfs( int u)
{
     int v;
    dfn[u] = low[u] = ++tot;
    ins[u] =  1;
    stack[top++] = u;
     for( int e = first[u]; e != - 1; e = edge[e].next)
    {
        v = edge[e].v;
         if(!dfn[v])
        {
            dfs(v);
            low[u] = min(low[u], low[v]);
        }
         else  if(ins[v])
        {
            low[u] = min(low[u], dfn[v]);
        }
    }
     if(dfn[u] == low[u])
    {
        scnt++;
         do
        {
            v = stack[--top];
            belong[v] = scnt;
            ins[v] =  0;
        } while(v != u);
    }
}

void Tarjan()
{
     for( int v =  1; v <= n; v++)  if(!dfn[v])
        dfs(v);
// Tarjan 

int toposort()
{
    queue< int> q;
     int tot2 =  0;
     for( int i =  1; i <= scnt; i++)  if(!ind[i]) q.push(i);
     if(q.size() >  1return  0;
     while(!q.empty())
    {
         int x = q.front(); q.pop();
        topo[++tot2] = x;
         for( int e = first2[x]; e != - 1; e = edge2[e].next)
        {
             int v = edge2[e].v;
             if(--ind[v] ==  0)
            {
                q.push(v);
            }
        }
         if(q.size() >  1return  0;
    }
     if(tot2 != scnt)  return  0;
     else  return  1;
// toposort 

void solve()
{
    Tarjan();
     for( int u =  1; u <= n; u++)  // 重构图 
    {
         for( int e = first[u]; e != - 1; e = edge[e].next)
        {
             int v = edge[e].v;
             if(belong[u] != belong[v])
            {
                ind[belong[v]]++;
                read_graph2(belong[u], belong[v]);
            }
        }
    }
     if(toposort()) printf( " Yes\n ");
     else printf( " No\n ");
}

int main()
{
     int T;
    scanf( " %d ", &T);
     while(T--)
    {
        init();
        scanf( " %d%d ", &n, &m);
         while(m--)
        {
             int u, v;
            scanf( " %d%d ", &u, &v);
            read_graph(u, v);
        }
        solve();
    }
     return  0;
}

 

你可能感兴趣的:(poj)