BZOJ-1123BLO Tarjan 点双连通分量
Posted DaD3zZ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ-1123BLO Tarjan 点双连通分量相关的知识,希望对你有一定的参考价值。
1123: [POI2008]BLO
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 970 Solved: 408
[Submit][Status][Discuss]
Description
Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。
Input
输入n<=100000 m<=500000及m条边
Output
输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。
Sample Input
5 5
1 2
2 3
1 3
3 4
4 5
1 2
2 3
1 3
3 4
4 5
Sample Output
8
8
16
14
8
8
16
14
8
HINT
Source
Solution
题意叙述不清。
题目大意:给定N个点M条边的无向图,问删除每个点后,对于有序数对(x,y)满足x,y互不连通的数对数。其中,被删掉的点也应被统计。
这种和删点,联通有关的,可以考虑割点/点双联通分量。
这个题也是,如果删除一个割点,那么答案个数就是裂成的几个块用乘法原理统计答案。如果删除一个非割点则可能会对其他点直接不影响。
可以考虑在Tarjan的过程中求解,我们额外记录一个size表示分成的联通块的大小,然后我们在Tarjan的过程中统计答案即可
Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> using namespace std; #define LL long long inline int read() { int x=0,f=1; char ch=getchar(); while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();} while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();} return x*f; } #define MAXN 100010 #define MAXM 500010 struct EdgeNode{int next,to;}edge[MAXM<<1]; int head[MAXN],cnt=1; inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;} inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);} int N,M; vector<int>BCC[MAXN]; #define Pa pair<int,int> Pa st[MAXM]; int top; int dfn[MAXN],low[MAXN],dfsn,son[MAXN],size[MAXN],cut[MAXN],bcc,belong[MAXN]; LL sum[MAXN]; inline void Tarjan(int now,int last) { dfn[now]=low[now]=++dfsn; LL su=0; size[now]=1; for (int i=head[now]; i; i=edge[i].next) if (!dfn[edge[i].to]) { st[++top]=make_pair(now,edge[i].to); son[now]++; Tarjan(edge[i].to,now); low[now]=min(low[now],low[edge[i].to]); size[now]+=size[edge[i].to]; if (dfn[now]<=low[edge[i].to]) { sum[now]+=su*size[edge[i].to]; su+=(LL)size[edge[i].to]; cut[now]=1; bcc++; BCC[bcc].clear(); int tnow=-1,tto=-1; while (tnow!=now && tto!=edge[i].to) { tnow=st[top].first,tto=st[top].second; top--; if (belong[tnow]!=bcc) BCC[bcc].push_back(tnow),belong[tnow]=bcc; if (belong[tto]!=bcc) BCC[bcc].push_back(tto),belong[tto]=bcc; } } } else if (dfn[edge[i].to]<dfn[now] && edge[i].to!=last) st[++top]=make_pair(now,edge[i].to),low[now]=min(low[now],dfn[edge[i].to]); if (last<0 && son[now]==1) cut[now]=0; sum[now]+=su*(N-su-1); } int main() { N=read(),M=read(); for (int x,y,i=1; i<=M; i++) x=read(),y=read(),InsertEdge(x,y); for (int i=1; i<=N; i++) if (!dfn[i]) Tarjan(i,-1); for (int i=1; i<=N; i++) printf("%lld\n",(LL)(sum[i]+N-1)*2); return 0; }
以上是关于BZOJ-1123BLO Tarjan 点双连通分量的主要内容,如果未能解决你的问题,请参考以下文章