CCF 高速公路

来源:互联网 发布:mac版软件下载大全 编辑:程序博客网 时间:2024/04/29 19:02

题意:给一个有向图,求可互通的点的对数(原点不计),这个问题可以转换为在一个有向图里找出所有的环,既然是找环,那么就显然是求强连通分量,我的写法是Tarjan算法

代码如下:

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<stack>using namespace std;const int maxn = 10000+7;int n, m, idx, ans, dfn[maxn], low[maxn];bool vis[maxn], ins[maxn];stack<int> s;vector<int> g[maxn];void Tarjan(int u){    dfn[u] = low[u] = ++idx;    ins[u] = true;    vis[u] = true;    s.push(u);    int vs = g[u].size();    for(int i=0; i<vs; i++)    {        int v = g[u][i];        if(!vis[v])        {            Tarjan(v);            low[u] = min(low[u], low[v]);        }        else if(ins[v]) low[u] = min(low[u], dfn[v]);    }    if(dfn[u] == low[u])    {        int cnt = 0, x;        do        {            x = s.top();            cnt++;            ins[x] = false;            s.pop();        }        while(x != u);        ans += cnt*(cnt-1)/2;    }}int main(){    while(~scanf("%d%d",&n,&m))    {        while(!s.empty()) s.pop();        for(int i=1; i<=n; i++) g[i].clear();        for(int i=0; i<m; i++)        {            int u,v;            scanf("%d%d",&u,&v);            g[u].push_back(v);        }        idx = ans = 0;        memset(vis,0,sizeof(vis));        memset(dfn,0,sizeof(dfn));        memset(low,0,sizeof(low));        memset(ins,0,sizeof(ins));        for(int i=1; i<=n; i++) if(!vis[i])            {                vis[i] = true;                Tarjan(i);            }        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击