poj 2762

Tarjan + Topsort
Tarjan 缩点
Topsort 判断

Topsort 判断:
在DAG中
若初始状态下存在多于1个入度为0的点
则说明这些 入度为0的点之间不会有路径可达
若不存在入度为0的点,则状态为Yes
若只存在1个入度为0的点,将该点指出的边删除
继续上述判断

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

const int N = 1010, M = N * 6;

#define gc getchar()

inline int read() {
    int x = 0; char c = gc;
    while(c < '0' || c > '9') c = gc;
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
    return x;
}

int head[N], head_2[N], cnt;
struct Node {int u, v, nxt;};
Node G[M], E[M];
int In[N], n, m;
int Low[N], Dfn[N], Stack[N], Belong[N], Scc, Tim, topp;
bool vis[N];

inline void Add_1(int u, int v) {G[++ cnt].v = v; G[cnt].nxt = head[u]; head[u] = cnt;}
inline void Add_2(int u, int v) {E[++ cnt].v = v; E[cnt].nxt = head_2[u]; head_2[u] = cnt; In[v] ++;}

inline void Clear() {
    memset(head, -1, sizeof head);
    memset(head_2, -1, sizeof head_2);
    memset(In, 0, sizeof In);
    memset(Low, 0, sizeof Low);
    memset(Dfn, 0, sizeof Dfn);
    memset(vis, 0, sizeof vis);
    topp = cnt = Scc = Tim = 0;
}

inline void Init() {
    n = read(), m = read();
    for(int i = 1; i <= m; i ++) Add_1(read(), read());
}

void Tarjan(int x) {
    Low[x] = Dfn[x] = ++ Tim;
    Stack[++ topp] = x; vis[x] = 1;
    for(int i = head[x]; ~ i; i = G[i].nxt) {
        int v = G[i].v;
        if(!Dfn[v]) {
            Tarjan(v);
            Low[x] = std:: min(Low[x], Low[v]);
        } else if(vis[v]) Low[x] = std:: min(Low[x], Low[v]);
    }
    if(Dfn[x] == Low[x]) {
        vis[x] = 0, Belong[x] = ++ Scc;
        while(Stack[topp] != x) {
            vis[Stack[topp]] = 0, Belong[Stack[topp]] = Scc;
            topp --;
        } topp --;
    }
}

inline void Rebuild() {
    cnt = 0;
    for(int u = 1; u <= n; u ++)
        for(int i = head[u]; ~ i; i = G[i].nxt)
            if(Belong[u] != Belong[G[i].v]) Add_2(Belong[u], Belong[G[i].v]);
}

void Topsort() {
    if(Scc == 1) {puts("Yes"); return ;}
    int Ans(0), flag;
    for(int i = 1; i <= Scc; i ++) if(!In[i]) Ans ++, flag = i;
    if(Ans > 1) {puts("No"); return ;}
    int temp = Scc;
    for(; temp; temp --) {
        Ans = 0;
        for(int i = head_2[flag]; ~ i; i = E[i].nxt) {
            int v = E[i].v;
            In[v] --;
            if(!In[v]) Ans ++, flag = v;
        }
        if(Ans > 1) {puts("No"); return ;}
        if(!Ans) {puts("Yes"); return ;}
    }
    puts("Yes"); return ;
}

void Work() {
    Clear();
    Init();
    for(int i = 1; i <= n; i ++) if(!Dfn[i]) Tarjan(i);
    Rebuild();
    Topsort();
}

int main() {
    int t = read();
    for(; t; t --, Work());
    return 0;
}

 

    

posted @ 2018-08-11 17:23  xayata  阅读(104)  评论(0编辑  收藏  举报