LOJ-10104(割点+dfs)

题目链接:传送门

思路:

求割点的同时求割点删除后所剩的不连通的点的对数,在遍历完成后回溯统计点的个数,具体操作见代码;

注意:结果是long long 类型。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn = 1e6+10;
int head[maxn],next[maxn],ver[maxn],tim;
LL size[maxn],ans[maxn];
int low[maxn],num[maxn],tot,m,n;
int MIN(int x,int y)
{
    return x<y?x:y;
}
void Init()
{
    memset(head,0,sizeof(head));
    memset(num,0,sizeof(num));
    memset(low,0,sizeof(low));
    memset(ans,0,sizeof(ans));
    memset(size,0,sizeof(size));
    tot=0;tim=0;
}
void addedge(int u,int v)
{
    ver[++tot]=v;next[tot]=head[u];head[u]=tot;
}
void Tarjan(int u)
{
    low[u]=num[u]=++tim;
    size[u]=1;
    int i,v,cnt=0;
    LL tp=0;
    for(i=head[u];i;i=next[i]){
        v=ver[i];
        if(!num[v]){
            cnt++;
            Tarjan(v);
            size[u]+=size[v]; //统计每一个相邻节点
            low[u]=MIN(low[u],low[v]);
            if(num[u]<=low[v]){
                ans[u]+=(LL)tp*size[v]; //已知区块节点数*相邻区块的节点数 
                tp+=size[v];//更新已知区块 
            }
        }
        else low[u]=MIN(low[u],num[v]);
    }
    ans[u]+=tp*(n-1-tp);//因为是连通图,所以要增加除了相邻节点以外图中剩余未访问的节点的数量和 
}
int main(void)
{
    int i,j,x,y;
    while(~scanf("%d%d",&n,&m)){
        Init();
        for(i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            addedge(x,y);
            addedge(y,x);
        }
        Tarjan(1); 
        for(i=1;i<=n;i++)
        printf("%lld
",(ans[i]+n-1)*2);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/2018zxy/p/10373874.html