POJ-2762 Going from u to v or from v to u? (强连通分量[Tarjan]&&(拓扑排序||树形DP))

此处有 目录↑
Going from u to v or from v to u?
http://poj.org/problem?id=2762
Time Limit: 2000MS   Memory Limit: 65536K
     

Description

In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?

Input

The first line contains a single integer T, the number of test cases. And followed T cases. 

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

The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.

Sample Input

1
3 3
1 2
2 3
3 1

Sample Output

Yes

题目大意:给定一个有向图,判断是否对任意两点u,v,有u可达v 或 v可达u?


先找出所有的强连通分量,则各强连通分量内是相互可达的,只用判断强连通分量之间是否至少单向可达

将各强连通分量缩成一点,建立新图,则新图是DAG

刚开始也认为只要从一个入度为0的点到出度为0的点的长度为总点数,就满足题意,否则不行,但是看见有人说不是只有一条链的情况下会输出Yes,于是放弃了

最终用拓扑排序AC,若某次队列中点的数目大于1(则这些点之间不能单向可达),则输出No,否则输出Yes

没有初始化indeg数组,导致WA了很久都没看出来...


解法一:Tarjan&&拓扑排序

#include 
#include 
#include 

using namespace std;

const int MAXN=1005;

int n,m,num,cnt,ans,top,head,tail;
int stak[MAXN],que[MAXN];
int low[MAXN],dfn[MAXN],color[MAXN],indeg[MAXN];//biocks[i]表示删掉i点后,能形成的连通块数
vector g[MAXN];
bool isIn[MAXN],mp[MAXN][MAXN];

void Tarjan(int u,int p) {
    stak[++top]=u;
    isIn[u]=true;
    dfn[u]=low[u]=++num;
    int v;
    for(int i=0;i1)//如果入度为0的点超过一个,则这些点不能相互单向可达
        return false;
    int u;
    while(head!=tail) {
        u=que[head++];
        for(int i=1;i<=cnt;++i) {
            if(mp[u][i]) {
                --indeg[i];
                if(indeg[i]==0)//入度为0的点入队
                    que[tail++]=i;
            }
        }
        if(tail-head>1)//如果入度为0的点超过一个,则这些点不能相互单向可达
            return false;
    }
    return true;
}

int main() {
    int T,s,e;
    scanf("%d",&T);
    while(T-->0) {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) {
            g[i].clear();
            dfn[i]=indeg[i]=0;
            isIn[i]=false;
        }
        while(m-->0) {
            scanf("%d%d",&s,&e);
            g[s].push_back(e);
        }

        cnt=num=top=0;//cnt表示强连通分量
        for(int i=1;i<=n;++i) {
            if(dfn[i]==0)
                Tarjan(i,0);
        }
        memset(mp,false,sizeof(mp));
        for(int i=1;i<=n;++i) {
            for(int j=0;j


解法二:Tarjan&&树形DP

又想了想,即使新图不是一条链,但是满足题意的情况下,必定有一条路径满足:入度为0的点到出度为0的点的所经过的点的个数等于所有点的个数

dp[i]表示从i点出发,一条路径上能经过的点数的最大值

#include 
#include 
#include 

using namespace std;

const int MAXN=1005;

int n,m,num,cnt,ans,top;
int stak[MAXN];
int low[MAXN],dfn[MAXN],color[MAXN],dp[MAXN];//biocks[i]表示删掉i点后,能形成的连通块数
vector g[MAXN],mp[MAXN];
bool isIn[MAXN],haveIndeg[MAXN];

void Tarjan(int u,int p) {
    stak[++top]=u;
    isIn[u]=true;
    dfn[u]=low[u]=++num;
    int v;
    for(int i=0;i1)
        return false;
    dfs(sta);
    return dp[sta]==cnt;//判断入度为0的点能达到的最大深度是否等于点的个数
}

int main() {
    int T,s,e;
    scanf("%d",&T);
    while(T-->0) {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) {
            g[i].clear();
            mp[i].clear();
            dfn[i]=0;
            isIn[i]=haveIndeg[i]=false;
        }
        while(m-->0) {
            scanf("%d%d",&s,&e);
            g[s].push_back(e);
        }

        printf("%s\n",Judge()?"Yes":"No");
    }
    return 0;
}


你可能感兴趣的:(HDU,连通分量,图论,DP)