hdu 2767 强联通

来源:互联网 发布:js 获取多个id 编辑:程序博客网 时间:2024/04/27 23:14

强联通+缩点判定加几条边强联通 

记个模版

#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll;   //记得必要的时候改成无符号const int maxn=20005;   //点数const int maxm=50005;   //边数const int INF=1000000000;struct EdgeNode{    int from;    int to;    int next;}edge[maxm];int head[maxn],cnt;void add(int x,int y){    edge[cnt].from=x;edge[cnt].to=y;edge[cnt].next=head[x];head[x]=cnt++;}void init(){    cnt=1;    memset(head,-1,sizeof(head));}int dfn[maxn],low[maxn],ins[maxn];int cixu,scc_count,n,ru[maxn],chu[maxn],sd[maxn];stack<int>S;void dfs(int u){    int v,x;    dfn[u]=low[u]=++cixu;    S.push(u);    ins[u]=1;    for(int i=head[u];i!=-1;i=edge[i].next)    {        v=edge[i].to;        if(!dfn[v]){            dfs(v);            low[u]=min(low[u],low[v]);        }        else if(ins[v])            //如果已经搜过,并且在栈里面,如果不在栈里面,说明该点属于其他的强连通分量里面            low[u]=min(low[u],dfn[v]);             //此处low代替dfn也是可以的,但是在tarjan求无向图的时候不能    }    if(dfn[u]==low[u])//表示u为此强连通分量第一个被发现的点,属于该强连通分量的所有的其他点都在栈中,他的上面    {        scc_count++;        do        {            x=S.top();            S.pop();            sd[x]=scc_count;            ins[x]=0;        }while(x!=u);    }}void tarjan(){    for(int i=1;i<=n;i++)sd[i]=i;   //缩点标记数组    memset(ins,0,sizeof(ins));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    cixu=scc_count=0;    for(int i=1;i<=n;i++)        //可能所给的图为不连通的图,分块,因此需要遍历所有的点    {        if(!dfn[i])            dfs(i);    }}void SD(){    int x,y,len=cnt;    init();    memset(ru,0,sizeof(ru));    memset(chu,0,sizeof(chu));    for(int i=1;i<len;i++){        x=sd[edge[i].from]; y=sd[edge[i].to];        if(x==y)continue;        add(x,y);        chu[x]++; ru[y]++;    }}int main(){    int m,i,T,p,sum,x,y;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        if(m==0){            printf("%d\n",n);            continue;        }        init(); sum=0; p=0;        for(i=1;i<=m;i++){            scanf("%d%d",&x,&y);            add(x,y);        }        tarjan();        SD();        if(scc_count==1){         //这个时候需要注意,直接缩成点了            printf("0\n");            continue;        }        for(i=1;i<=scc_count;i++){            if(ru[i]==0)p++;            if(chu[i]==0)sum++;        }        printf("%d\n",max(p,sum));    }    return 0;}


0 0
原创粉丝点击