仙人掌圖

題目鏈接: http://acm.hdu.edu.cn/showproblem.php?pid=3594

性質:

先給出一個仙人掌的詳解: https://files-cdn.cnblogs.com/files/ambition/cactus_solution.pdf

我稍微說一下自己目前大概的理解吧,仙人掌樹剛剛入門做完板題的說,網上也沒什麼人解釋,只能自己先大概講講,如果有問題的歡迎指正。

仙人掌圖按照圖的邊的方向性分兩種,有向仙人掌圖和無向圖仙人掌圖。

有向圖仙人掌圖

有向圖仙人掌圖,按照目前能看得到的資料,首先要滿足的是一個整個的強連通圖,每一條邊必須在且僅在一個強連通塊內。

所以就有了它的三條性質;

① 仙人掌圖的 dfsdfs 樹不存在橫向邊。(橫向邊的定義可以看上面鏈接中的圖,大概意思就是dfs的過程中不存在訪問到的新點是曾經被訪問過的點)
low[v]<=dfn[u]low[v] <= dfn[u] ( fa[v]=ufa[v]=u )
③ 設某個點 uu 有可到達的點集爲 S(u)S(u) 那麼滿足條件 vS(u)v\in S(u)low[v]<dfn[u]low[v]<dfn[u] 的點 vv 的個數小於 22vv 也可能爲 uu 的父鏈結點)

無向仙人掌圖

已有知識來看,無向仙人掌圖中要求所有的邊,是橋或者只在一個簡單環中。

bzoj上好像有一些相應的題目。。但是現在oj炸了。。我得先去學了。。

hdu3594代碼
代碼

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep_e(i,u) for(int i=head[u];~i;i=nex[i])
using namespace std;
const int maxn=20005;
const int maxm=50005;
typedef long long ll;
int dfn[maxn],low[maxn],sta[maxn],top,flag,n,belong[maxn];
int head[maxn],to[maxm],nex[maxm],cnt,vis[maxn],qiang;
void add(int u,int v){
    to[cnt]=v;nex[cnt]=head[u];
    head[u]=cnt++;
}

void tarjan(int x){
    if(flag) return ;
    dfn[x]=low[x]=++cnt;
    sta[++top]=x;
    rep_e(i,x){
        int v=to[i];
        if(vis[v]) flag=1;
        if(!dfn[v]){
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else if(!belong[v]) low[x]=min(low[x],low[v]);
    }
    if(dfn[x]==low[x]){
        qiang++;
        if(qiang>1) {flag=1; return ;}
        while(1){
            int u=sta[top--];
            belong[u]=qiang;
            if(u==x) break;
        }
    }
    vis[x]=1;
}
void init(){
    cnt=0; flag=0; top=0;qiang=0;
    rep(i,1,n) {
        head[i]=-1,vis[i]=0;
        dfn[i]=low[i]=0;
        belong[i]=0;
    }
}
int main(){
    int T; scanf("%d",&T);
    while(T--){

        scanf("%d",&n);
        init();
        int x,y;
        while(~scanf("%d%d",&x,&y)){
            if(x==0&&y==0) break;
            x++,y++;
            add(x,y);
        }
        rep(i,1,n){
            if(!dfn[i]) tarjan(i);
        }
        if(flag) {
            printf("NO\n"); continue;
        }
        rep(u,1,n){
            int nu=0;
            rep_e(i,u){
                int v=to[i];
                if(low[v]>dfn[u]) flag=1;
                if(low[v]<dfn[u]) nu++;
            }
            if(nu>=2) flag=1;
        }
        if(flag) printf("NO\n");
        else printf("YES\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章