传送门:洛谷 P3469
题目描述
在Byteotia有n个城镇。 一些城镇之间由无向边连接。 在城镇外没有十字路口,尽管可能有桥,隧道或者高架公路(反正不考虑这些)。每两个城镇之间至多只有一条直接连接的道路。人们可以从任意一个城镇直接或间接到达另一个城镇。 每个城镇都有一个公民,他们被孤独所困扰。事实证明,每个公民都想拜访其他所有公民一次(在主人所在的城镇)。所以,一共会有n*(n-1)次拜访。
不幸的是,一个程序员总罢工正在进行中,那些程序员迫切要求购买某个软件。
作为抗议行动,程序员们计划封锁一些城镇,阻止人们进入,离开或者路过那里。
正如我们所说,他们正在讨论选择哪些城镇会导致最严重的后果。
编写一个程序:
读入Byteotia的道路系统,对于每个被决定的城镇,如果它被封锁,有多少访问不会发生,输出结果。
输入输出格式
第一行读入n,m,分别是城镇数目和道路数目(1≤n≤100 000, 1≤m≤500 000)
城镇编号1~n
接下来m行每行两个数字a,b,表示a和b之间有有一条无向边
输出n行,每行一个数字,为第i个城镇被锁时不能发生的访问的数量。
输入 #1
5 5
1 2
2 3
1 3
3 4
4 5
输出 #1
8
8
16
14
8
对于非割点,答案是2(n-1) (因为它不能影响别的点对连通性,能影响的只是别人到它以及它到别人)
对于割点,去掉后一个强连通分量会变成几块,那么这几块中不同块的两个点肯定就无法联通了,答案也就是每组块的点的数量互相乘出来,再加上2(n-1)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int N=110000;
int n,m,idx,k;
int dfn[N],low[N],size[N];
int vis[N],head[N];
ll ans[N];
vector<ll> g[N];//存割去i点后,剩下几块,每块的点的数目
struct edge
{
int to,next;
}e[10*N];
void add(int u,int v)
{
e[k].to=v;
e[k].next=head[u];
head[u]=k++;
}
void tarjan(int u)
{
int v;
dfn[u]=low[u]=++idx;
size[u]++;
int temp=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
v=e[i].to;
if(!dfn[v])
{
tarjan(v);
size[u]+=size[v];
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
ans[u]+=(ll)temp*size[v];
temp+=size[v];
//vis[u]=1;
//g[u].push_back(size[v]);
}
}
else
{
low[u]=min(low[u],dfn[v]);
}
}
ans[u]+=(ll)temp*(n-temp-1);
/*if(vis[u]&&n-temp-1!=0)
{
g[u].push_back(n-temp-1);
}*/
}
int main()
{
int a,b;
memset(head,-1,sizeof(head));
k=1,idx=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
printf("%I64d\n",(ans[i]+n-1)*2);
}
return 0;
}