24h購物| | PChome| 登入
2013-10-06 20:56:49| 人氣1,549| 回應0 | 上一篇 | 下一篇

[UVA][SCC變形] 10510 - Cactus

推薦 0 收藏 0 轉貼0 訂閱站台

Problem B
Cactus
Input: standard input
Output: standard output

A directed graph is a set V of vertices and a set of E ∈ {V x V} edges. An edge (u,v) is said to be directed from u to v (the edge (v,u) has the opposite direction). A directed cycle in a directed graph is a sequence of edges

(u1, v1), (u2, v2),…, (uk, vk)

such that ui+1 = vi for i = 1, …, k-1, and u1=vk. The directed cycle is simple if ui ≠ uj whenever i ≠ j (i.e., if it does not pass through a vertex twice).

In a strongly connected directed graph, there is for every pair u,v of vertices some directed cycle (not necessarily simple) that visits both u and v.

A directed graph is a cactus if and only if it is strongly connected and each edge is part of exactly one directed simple cycle. The first graph is a cactus, but the second one is not since for instance the edge (0,1) is in two simple cycles.

The reason for the name is that a "cactus" consists of several simple cycles connected to each other in a tree-like fashion, making it look somewhat like a cactus.

Problem

Write a program that given a directed graph determines if it is a cactus or not. The graph can have several thousand vertices.

Input

The first line contains an integer which is the number of test cases (less than 20). Each test case starts a line with an integer n ≥ 0 followed by line with an integer m ≥ 0 giving the number of vertices (n) and edges (m) in a graph (at most 10,000 of each). The vertices are numbered 0 through n-1. The following m lines describe the edges as pairs of numbers u v denoting an edge directed from u to v. There will never be more than one edge from u to v for any pair of vertices u and v. There are no loops, i.e., no edges from a vertex to itself.

Output

For each test case output a single line with a single string. Output "YES" if the graph is a cactus, and output "NO" if it is not.

Sample Input

2
4
5
0 1
1 2
2 0
2 3
3 2
4
5
0 1
1 2
2 3
3 0
1 3

Sample Output

YES
NO

Problem setter: Mikael Goldmann

題目描述:


判斷這張圖是否會符合,恰好是一個 SCC 元件,以及每一條邊都只出現過一次於一個環上。

題目解法:


一樣使用 SCC 的遞迴樹,對於 back edge 時,將整個環標記。

因此不同於一般 SCC 寫法,需要多紀錄 parent。

而有些邊可能會使用多次,由於只看 back edge,多餘向下也肯定是多餘的邊。

#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <deque>
#include <algorithm>
using namespace std;
struct edge {
    int to, cnt;
    edge(int a=0, int b=0):
        to(a) , cnt(b) {}
};
vector<edge> g[10005];
int vfind[10005], findIdx;
int stk[10005], stkIdx;
int in_stk[10005], visited[10005];
//
int parent[10005];
edge *parentUsed[10005];
int checkflag;
int scc(int nd) {
    in_stk[nd] = visited[nd] = 1;
    stk[++stkIdx] = nd;
    vfind[nd] = ++findIdx;
    int mn = vfind[nd], i;
    for(i = 0; i < g[nd].size(); i++) {
        if(!visited[g[nd][i].to]) {
            parent[g[nd][i].to] = nd;//this problem process
            parentUsed[nd] = &g[nd][i];//this problem process
            mn = min(mn, scc(g[nd][i].to));
        }
        if(in_stk[g[nd][i].to]) {
            mn = min(mn, vfind[g[nd][i].to]);
            if(vfind[g[nd][i].to] <= vfind[nd]) {//this problem process
                // cycly find.
                if(checkflag)    continue;
                g[nd][i].cnt++;
                if(g[nd][i].cnt > 1)    checkflag = 1;
                int next = nd;
                while(checkflag == 0) {
                    parentUsed[parent[next]]->cnt++;
                    if(parentUsed[parent[next]]->cnt > 1)    checkflag = 1;
                    next = parent[next];
                    if(next == g[nd][i].to)
                        break;
                }
            }
        }
    }
    if(mn == vfind[nd]) {
        do {
            in_stk[stk[stkIdx]] = 0;
        } while(stk[stkIdx--] != nd);
    }
    return mn;
}
int main() {
    int testcase;
    int n, m;
    int i, j, k, x, y;
    scanf("%d", &testcase);
    while(testcase--) {
        scanf("%d %d", &n, &m);
        for(i = 0; i < n; i++)
            g[i].clear();
        for(i = 0; i < m; i++) {
            scanf("%d %d", &x, &y);
            g[x].push_back(edge(y, 0));
        }
        memset(visited, 0, sizeof(visited));
        memset(in_stk, 0, sizeof(in_stk));
        int component = 0;
        checkflag = 0;
        for(i = 0; i < n; i++) {
            if(visited[i] == 0) {
                findIdx = stkIdx = 0;
                if(++component > 1)    break;
                scc(i);
            }
        }
        for(i = 0; i < n; i++)
            for(j = 0; j < g[i].size(); j++)
                if(g[i][j].cnt != 1)
                    checkflag = 1;
        if(component > 1)    checkflag = 1;
        puts(checkflag == 0 ? "YES" : "NO");
#define debug 0
#if debug == 1
        for(i = 0; i < n; i++)
            for(j = 0; j < g[i].size(); j++)
                printf("%d -> %d %d\n", i, g[i][j].to, g[i][j].cnt);
        printf("%d %d\n", checkflag, component);
#endif
    }
    return 0;
}

台長: Morris
人氣(1,549) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 教育學習(進修、留學、學術研究、教育概況) | 個人分類: UVA |
此分類下一篇:[UVA][math] 10287 - Gifts in a Hexagonal Box
此分類上一篇:[UVA][DLX] 211 - The Domino Effect

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文