Live2D

【LGOJ3469】BLO-Blockade

n个城市由n-1条道路连接
依次输出,如果每个点分别被关闭(无法通过),有多少对点之间无法相互到达

最近写tarjan写得有点入魔
所以这还是一道割点的板子题
对于每个节点,如果它不是割点,那只有其它点到它,以及它到其他点无法到达
所以答案为\(2*(n-1)\)
如果是割点,只需要统计一下连通块大小,计算一下就好

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 100005
#define M 500005
using namespace std;

ll n,m,u,v;

struct Edge
{
	int next,to;
}edge[M<<1];
int cnt=0,head[M];

inline void add_edge(int from,int to)
{
	edge[++cnt].next=head[from];
	edge[cnt].to=to;
	head[from]=cnt;
}

template<class T>inline void read(T &res)
{
	char c;T flag=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

int tms=0,low[N],dfn[N];
ll siz[N],ans[N];
bool iscut[N];
void tarjan(int u)
{
	low[u]=dfn[u]=++tms;
	int flag=0;
	ll sum=0;
	siz[u]=1;
	for(register int i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
			siz[u]+=siz[v];
			if(dfn[u]<=low[v])
			{
				flag++;
				sum+=siz[v];
				ans[u]+=siz[v]*(n-siz[v]);
				if(u!=1||flag>1) iscut[u]=true;
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
	if(!iscut[u]) ans[u]=2LL*(n-1);
	else ans[u]+=(ll)(n-sum-1)*(sum+1)+(n-1);
}

int main()
{
	read(n);read(m);
	for(register int i=1;i<=m;++i)
	{
		read(u);read(v);
		add_edge(u,v);
		add_edge(v,u);
	}
	tarjan(1);
//	for(register int i=1;i<=n;++i) cout<<iscut[i]<<" ";cout<<endl; 
	for(register int i=1;i<=n;++i) printf("%lld\n",ans[i]);
	return 0;
}
posted @ 2019-10-11 18:19  tqr06  阅读(194)  评论(0编辑  收藏  举报