码迷,mamicode.com
首页 > 其他好文 > 详细

HDU - 3594 Cactus(仙人掌图)

时间:2015-08-12 01:18:57      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:给出仙人掌图的定义:
1.必须是强连通
2.每条边只能属于一个环

解题思路:在tarjan算法中加入点东西就可以判断了
只要该点能连到之前的点,那么形成环了,找到这个环的所有的边,并标记
如果有一条边被标记了两次了,那图就不是仙人掌图了

关键是怎么找到这个环的所有边,我们可以引入另一个栈,这个栈存放的是边的序号
假设当前点为u,u点连回之前的点是v,那么就从栈里面找边,找到出发点为v的边为止,找到的这些边都是环上的边,这个和tarjan算法的找同一个连通分量的点的道理是一样

#include <cstdio>
#include <cstring>
#pragma comment(linker, "/STACK:102400000,102400000")
#define N 20010
#define M 50010
#define min(a,b) ((a) < (b) ? (a) : (b))

struct Edge{
    int from, to, next, id;
}E[M];

int head[N], pre[N], lowlink[N], sccno[N], stack[N], stack2[M];
int tot, n, scc_cnt, dfs_clock, top, top2;
int queue[M];
bool vis[M];
bool flag;

void AddEdge(int from, int to) {
    E[tot].from = from;
    E[tot].to = to;
    E[tot].next = head[from];
    E[tot].id = tot;
    head[from] = tot++;
}

void init(){ 
    scanf("%d", &n);
    memset(head, -1, sizeof(head));
    tot = 0;

    int u, v;
    while (scanf("%d%d", &u, &v) && u + v) {
        AddEdge(u, v);
    }
}

void dfs(int u) {
    pre[u] = lowlink[u] = ++dfs_clock;
    stack[++top] = u;

    for (int i = head[u]; i != -1; i = E[i].next) {
        int v = E[i].to;
        stack2[++top2] = E[i].id;
        if (!pre[v]) {
            dfs(v);
            lowlink[u] = min(lowlink[u], lowlink[v]);
        }
        else if(!sccno[v]) {
            lowlink[u] = min(lowlink[u], pre[v]);
            int tmp = top2;
            while (1){
                int id = stack2[top2--];
                if (vis[id])
                    flag = true;
                vis[id] = true;
                if (E[id].from == v)
                    break;
            }
            top2 = tmp;
        }
        top2--;
    }

    int x;
    if (pre[u] == lowlink[u]) {
        scc_cnt++;
        while (1) {
            x = stack[top--];
            sccno[x] = scc_cnt;
            if (x == u)
                break;
        }
    }
}

void solve() {
    memset(pre, 0, sizeof(pre));
    memset(sccno, 0, sizeof(sccno));
    memset(vis, 0, sizeof(vis));
    dfs_clock = top = top2 = scc_cnt = 0;
    flag = false;
    dfs(0);

    for (int i = 0; i < n; i++) {
        if (sccno[i] != 1) {
            printf("NO\n");
            return ;
        }
    }

    if (flag) 
        printf("NO\n");

    else
        printf("YES\n");
}

int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        init();
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU - 3594 Cactus(仙人掌图)

标签:

原文地址:http://blog.csdn.net/l123012013048/article/details/47432905

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!