题目链接:传送门
思路:
求割点的同时求割点删除后所剩的不连通的点的对数,在遍历完成后回溯统计点的个数,具体操作见代码;
注意:结果是long long 类型。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }