Luogu2341 受歡迎的牛

好題。

在有向圖中找到強連通子圖,縮點,記上裏面有幾頭牛,變成DAG。

然後找出出度爲0的點。如果這樣的點的數量不等於1顯然輸出0。否則答案就是這個點的原點數。

爲了方便,反向建邊,變統計出度爲入度。枚舉每一個原圖的點u,如果找到原圖中與u點相連的v不屬於同一個scc,那麼入度+1。(即不重建圖。

打了四遍這個題真TM爽

#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 10001
#define maxm 50001
using namespace std;
int head[maxn];
struct edge{
    int to, nxt;
}e[maxm];
int n, m, tot, top, cnt, col;
int dfn[maxn], st[maxn], low[maxn], scc[maxn];
int sl[maxn], ind[maxn];
void add(int u, int v){
    e[++tot].nxt=head[u];
    e[tot].to=v;
    head[u]=tot;
}
void tarjan(int u){
    dfn[u]=low[u]=++cnt;
    st[++top]=u;
    for(int i=head[u]; i; i=e[i].nxt){
        int v=e[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u], low[v]);
        }else if(!scc[v])
            low[u]=min(low[u], dfn[v]);
    }
    if(low[u]==dfn[u]){
        scc[u]=++col;
        ++sl[col];
        while(st[top]!=u){
            ++sl[col];
            scc[st[top]]=col;
            top--;
        }
        top--;
    }
}
int main(){
    scanf("%d%d", &n, &m);
    int x, y;
    for(int i=1; i<=m; i++){
        scanf("%d%d", &x, &y);
        add(y,x);
    }
    for(int i=1; i<=n; i++)
        if(!dfn[i]) tarjan(i);
    for(int i=1; i<=n; i++)
        for(int j=head[i]; j; j=e[j].nxt){
            int v=e[j].to;
            if(scc[i]!=scc[v])
                ind[scc[v]]++;
        }
    int ans=0, indtj=0;
    for(int i=1; i<=col; i++)
        if(!ind[i])
            ans=sl[i], indtj++;
    if(indtj==1)
        printf("%d", ans);
    else printf("0");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章