POJ - 2762 Going from u to v or from v to u?(拓扑排序+强连通分量)

来源:互联网 发布:utorrent mac 设置 编辑:程序博客网 时间:2024/05/11 23:12

题目大意:给出N个点,M条有向边,问是否任意两点u,v都满足u能到达v或者v能到达u

解题思路:强连通分量内的所有的点都满足,接着要判断一下其他的点能否满足了
求出所有的强连通分量,接着缩点,用桥连接,形成新的图(以下所说的点都是指新的图的点)
如果一个点同时指向另外两个不同的点,那么这两个点之间肯定是不能相互到达的,所以拓扑排序一下,就可以知道是否符合了

#include <cstdio>#include <cstring>#define min(a,b) ((a) < (b) ? (a) : (b))#define N 10100#define M 60100struct Edge{    int from, to, next;}E[M];struct Node{    int x, y;}node[M];int n, m, tot, dfs_clock, top, scc_cnt;int head[N], pre[N], stack[N], sccno[N], lowlink[N], in[N];void AddEdge(int u, int v) {    E[tot].from = u;    E[tot].to = v;    E[tot].next = head[u];    head[u] = tot++;}void init() {    scanf("%d%d", &n, &m);    memset(head, -1, sizeof(head));    tot = 0;    int u, v;    for (int i = 0; i < m; i++) {        scanf("%d%d", &node[i].x, &node[i].y);        AddEdge(node[i].x, node[i].y);    }}void dfs(int u) {    pre[u] = lowlink[u] = ++dfs_clock;    stack[++top] = u;    int v;    for (int i = head[u]; i != -1; i = E[i].next) {        v = E[i].to;        if (!pre[v]) {            dfs(v);            lowlink[u] = min(lowlink[u], lowlink[v]);        }        else if (!sccno[v]) {            lowlink[u] = min(lowlink[u], pre[v]);        }    }    if (pre[u] == lowlink[u]) {        scc_cnt++;        while (1) {            v = stack[top--];            sccno[v] = scc_cnt;            if (v == u) break;        }    }}int find() {    int cnt = 0, num;    for (int i = 1; i <= scc_cnt; i++) {        if (in[i] == 0) {            cnt++;            num = i;        }    }    if (cnt == 1)        return num;    return 0;}bool TopoOrder(){    int cnt = 0;    int u;    while (u = find()) {        in[u] = -1;        for (int i = head[u]; i != -1; i = E[i].next) {            in[E[i].to]--;        }        cnt++;    }    return cnt == scc_cnt;}void solve() {    memset(pre, 0, sizeof(pre));    memset(sccno, 0, sizeof(sccno));    dfs_clock = top = scc_cnt = 0;    for (int i = 1; i <= n; i++)        if (!pre[i])            dfs(i);    if (scc_cnt == 1) {        printf("Yes\n");        return ;    }    memset(in, 0, sizeof(in));    memset(head, -1, sizeof(head));    tot = 0;    int u, v;    for (int i = 0; i < m; i++) {        u = sccno[node[i].x];        v = sccno[node[i].y];        if (u != v) {            in[v]++;            AddEdge(u, v);        }    }    int ans = 0;    for (int i = 1; i <= scc_cnt; i++)        if (in[i] == 0)            ans++;    if (ans > 1) {        printf("No\n");        return ;    }    if (TopoOrder())         printf("Yes\n");    else        printf("No\n");}int main() {    int test;    scanf("%d", &test);    while (test--) {        init();        solve();    }    return 0;}
0 0
原创粉丝点击