2017 乌鲁木齐赛区网络赛 Islands(【点强连通问题】【缩点+点强连通分量】)

来源:互联网 发布:张大奕的淘宝店劣质 编辑:程序博客网 时间:2024/05/16 17:29

题目链接:https://nanti.jisuanke.com/t/16955
【中文题意】给你一个有向图,然后让你加最少的边使得全图强连通(即从任意一个点出发,可以到达剩余的所有点)。
【思路分析】非常经典的板子题。先找强连通分量,然后缩点后求边的条数。
【AC代码】

#include<cstdio>#include<cstring>#include<cmath>#include<stack>#include<queue>#include<vector>#include<map>#include<algorithm>using namespace std;#define maxn 10005vector<int>G[maxn];int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt,n,m;stack<int>S;void dfs(int u){    pre[u] = lowlink[u] = ++dfs_clock;    S.push(u);    for(int i = 0; i < G[u].size(); i++)    {        int v = G[u][i];        if(!pre[v])        {            dfs(v);            lowlink[u] = min(lowlink[u],lowlink[v]);        }        else if(!sccno[v])        {            lowlink[u]=min(lowlink[u],pre[v]);        }    }    if(lowlink[u]==pre[u])    {        scc_cnt++;        for(;;)        {            int x=S.top();            S.pop();            sccno[x]=scc_cnt;            if(x==u)break;        }    }}void find_scc(int n){    dfs_clock = scc_cnt = 0;    memset(sccno, 0, sizeof(sccno));    memset(pre,0,sizeof(pre));    for(int i = 0; i < n ; i++)    {        if(!pre[i])dfs(i);    }}int in[maxn],out[maxn];int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        for(int i=0; i<n; i++)G[i].clear();        for(int i=0; i<m; i++)        {            int u,v;            scanf("%d%d",&u,&v);            u--;            v--;            G[u].push_back(v);        }        find_scc(n);        //printf("%d***\n",scc_cnt);        /*for(int i=0; i<n; i++)        {            printf("%d+++\n",sccno[i]);        }*/        for(int i=1; i<=scc_cnt; i++)        {            in[i]=out[i]=1;        }        for(int u=0; u<n; u++)        {            for(int i=0; i<G[u].size(); i++)            {                int v=G[u][i];                if(sccno[u]!=sccno[v])                {                    in[sccno[v]]=out[sccno[u]]=0;                }            }        }        int a = 0,b=0;        for(int i=1; i<=scc_cnt; i++)        {            if(in[i])a++;            if(out[i])b++;        }        int ans = max(a,b);        if(scc_cnt==1)        {            printf("0\n");        }        else        {            printf("%d\n",ans);        }    }    return 0;}
原创粉丝点击