BZOJ1051

傳送門:BZOJ1051

Tarjan算法求強聯通分量,縮點,記錄出度。
現學的Tarjan算法……++cnt寫錯了orz。
最近眼睛不舒服,做題好慢……

代碼上的小細節見下。

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <stack>
#include <vector>
using namespace std;

struct Edge{
    int u,v;
};

Edge edge[50005];
stack<int> Q;
int low[50005],dfn[50005];
vector<int> G[50005];
bool instack[50005];
int cnt;
int where[50005];
int scc;
int out[50005];
int have[50005];
int n,m;
int ans;

void Tarjan(int root)
{
    low[root]=dfn[root]=++cnt;
    instack[root]=true;
    Q.push(root);
    for(int i=0;i<G[root].size();i++){
        int u=G[root][i];
        if(low[u]==0){
            Tarjan(u);
            low[root]=min(low[root],low[u]);
        }
        else if(instack[u])
            low[root]=min(low[root],dfn[u]);
    }
    if(low[root]==dfn[root]){
        scc++;
        int v;
        do{
            v=Q.top();
            where[v]=scc;
            instack[v]=false;
            have[scc]++;
            Q.pop();
        }while(v!=root);
    }
}

void Rebuild()
{
    for(int i=1;i<=m;i++)
        if(where[edge[i].u]!=where[edge[i].v])
            out[where[edge[i].u]]++;
}

void First()
{
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            Tarjan(i);
    Rebuild();
}

void Solve()
{
    int jec=0;
    for(int i=1;i<=scc;i++){
        if(out[i]==0)
            jec++,ans=i;
        //printf("%d\n",out[i]);
    }
    printf("%d\n",jec==1?have[ans]:0);
}

void Close()
{
    fclose(stdin);
    fclose(stdout);
}

void Readdata()
{
    freopen("loli.in","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&edge[i].u,&edge[i].v);
        G[edge[i].u].push_back(edge[i].v);
    }
}
int main()
{
    Readdata();
    First();
    Solve();
    Close();
    return 0;
}
發佈了54 篇原創文章 · 獲贊 5 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章