【C ++】「2010ACM-ICPC多大学研修コンテスト」「灘オープン2002」サボテン

【ソース】

2010 ACM-ICPCマルチ大学教育コンテスト(16) -ホストNUDTによって
灘オープン2002
HDU-3594
UVA-10510
Kattis-サボテン
vjudge

上記の質問バンクの質問の一般的な意味は同じですが、質問の説明と入力形式が異なります。コードはHDUの対象となります。

【トピック説明】

1.強く接続されたグラフです。
2.グラフの各エッジは円に属し、1つの円にのみ属します。
このグラフをCACTUSと呼びます。

1.これは強く接続されたグラフです。
2.グラフの各辺は円に属し、1つの円にのみ属します。
この写真をサボテンの写真と呼びます。
ここに画像の説明を挿入

上図のような例があります。左はサボテンですが、右はサボテンではありません。右のグラフのエッジ(0、1)は、(0、1、3)と(0、1、2、3)の2つの円に属しているためです。

上の写真に例があります。左側はサボテンの図ですが、右側はそうではありません。右の図のエッジ(0、1)は、(0、1、3)と(0、1、2、3)の2つの円に属しているためです。

【入力フォーマット】

入力は、いくつかのテストケースで構成されています。最初の行には、テストケースの数を表す整数T(1 <= T <= 10)が含まれています。
いずれの場合も、最初の行には、ポイントの数を表す整数n(1 <= n <= 20000)が含まれています。
次の線、各線には2つの数字aとbがあり、一方向のエッジ(a-> b)を表します。各ケースは(0 0)で終わります。
注意:エッジの総数は50000を超えません。

入力にはいくつかのテストケースが含まれています。最初の行には、テストケースの数を表す整数T(1 <= T <= 10)が含まれています。
いずれの場合も、最初の行には、ポイントの数を表す整数n(1 <= n <= 20000)が含まれています。
次の行では、各行に2つの番号aとbがあり、一方向のエッジ(a-> b)を表します。各ケースは(0 0)で終わります。
注:エッジの総数は50000を超えません。

[出力フォーマット]

いずれの場合も、このグラフがサボテンであるかどうかを表す「YES」または「NO」を含む行を出力します。

いずれの場合も、出力行には「はい」または「いいえ」が含まれ、画像がサボテンであるかどうかを示します。

【サンプル入力】

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

【サンプル出力】

YES
NO

[分析]

問題解決のアイデア:

1.まず、最初にtarjanアルゴリズムのアプリケーションを習得する必要があります。
2.サボテングラフの3つの特性を理解する必要
があります。(1)サボテンdfsグラフに水平エッジを含めることはできません。各ポイントは、強い接続コンポーネントにのみ表示できることを理解してください。
(2)low [v] <dfn [u]、ここでuはvの親ノードです。
(3)a [u] + b [u] <2、a [u]はuノードの息子ノードです。 a [u]低い値がuよりも小さいdfn値。b [u]は、uの逆エッジの数です。

3つのプロパティのいずれかが満たされない場合、それはサボテン図ではありません。

【コード】

#pragma GCC optimize(3,"Ofast","inline")

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

using namespace std;

typedef long long LL;

const int N=5e5;
const int inf=1e9;

struct Node {
    
    
    int to,nt;
} e[N];

int n,m,cnt,tot,num,top,index,flag;
int h[N],fa[N],dfn[N],low[N],instack[N],stap[N],belong[N],vis[N];

inline void add(int x,int y) {
    
    
    e[cnt].to=y;
    e[cnt].nt=h[x];
    h[x]=cnt++;
}

void tarjan(int u) {
    
    
    int v;
    dfn[u]=low[u]=++index;
    instack[u]=1;
    stap[++top]=u;
    for(int i=h[u]; i!=-1; i=e[i].nt) {
    
    
        v=e[i].to;
        if(!dfn[v]) {
    
    
            fa[v]=u;
            tarjan(v);
            if(low[u]>low[v]) low[u]=low[v];
        } else if(instack[v]) {
    
    
            if(dfn[v]<low[u]) low[u]=dfn[v];
            int tmp=u;
            while(v!=fa[tmp]) {
    
    
                vis[tmp]++;
                if(vis[tmp]>1) {
    
    
                    flag=1;
                    return;
                }
                tmp=fa[tmp];
            }
        }
    }
    if(low[u]==dfn[u]) {
    
    
        tot++;
        do {
    
    
            v=stap[--top];
            instack[v]=0;
            belong[v]=tot;
        } while(v!=u);
    }
}

int main() {
    
    
    int T;
    scanf("%d",&T);
    while(T--) {
    
    
        tot=top=index=flag=0;
        memset(h,-1,sizeof(h));
        memset(fa,0,sizeof(fa));
        memset(dfn,0,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        memset(vis,0,sizeof(vis));
        int n;
        scanf("%d",&n);
        while(1) {
    
    
            int x,y;
            scanf("%d%d",&x,&y);
            if(x==0 && y==0) break;
            add(x+1,y+1);
        }
        for(int i=1; i<=n; i++) {
    
    
            if(!dfn[i]) tarjan(i);
        }
        if(tot>1 || flag) {
    
    
            puts("NO");
        } else puts("YES");
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/Ljnoit/article/details/105902179
おすすめ