暂无链接
Booom
问题描述】
三思而后行。
企鹅国从强盗海豹手里忽悠来了一些钱用于修路,这样企鹅国又多了一些道路了!(当然可能一条也没多,还是一颗树)。
海豹准备报复企鹅,于是准备悄悄轰炸掉企鹅一座城市。企鹅国国王㪷㪷非常慌,他现在希望得到损失预估值,也就是对于每一座城市,如果这座城市被炸掉了,那么有多少对城市不再连通?(被炸掉的城市也需要算入内,详见样例)
这里的城市对,是指有序点对(i,j),i≠j的数目。
【输入格式】
第一行两个整数N,M,表示企鹅国城市数目以及边数。
接下来M行,每行两个整数u,v,表示有一条连接城市u和城市v的道路。
【输出格式】
输出N行,每行一个整数,第i行表示城市i被炸掉之后,有多少对城市不能互相到达。
【输入样例】
5 5
1 2
2 3
1 3
3 4
4 5
【输出样例】
8
8
16
14
8
【数据范围】
对50%的输入数据 :N≤500,M≤10000;
对100%的输入数据 :N≤100000,M≤500000。
数据非常有梯度。
题解
出题人题解:
然而这么简单的题我还是爆零了,全场暴力写挂,我为什么这么优秀???
考试的时候想把每个割点的所有儿子大小算出来,然而每次只需要算出一个就可以了。
还有一堆人做过原题。
我好菜啊orz。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int M=1e5+5;
int n,m,df,dfn[M],low[M],siz[M];
ll ans[M];
vector<int>mmp[M];
void in()
{
int a,b;scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)scanf("%d%d",&a,&b),mmp[a].push_back(b),mmp[b].push_back(a);
}
void tarjan(int v)
{
dfn[v]=low[v]=++df;siz[v]=1;int to,pre=0;
for(int i=mmp[v].size()-1;i>=0;--i)
{
to=mmp[v][i];
if(!dfn[to])
{
tarjan(to);siz[v]+=siz[to];low[v]=min(low[v],low[to]);
if(dfn[v]<=low[to]){ans[v]+=(ll)pre*siz[to];pre+=siz[to];}
}
low[v]=min(low[v],dfn[to]);
}
ans[v]+=(ll)pre*(n-pre-1);
}
void ac(){tarjan(1);for(int i=1;i<=n;++i)printf("%lld\n",ans[i]+n-1<<1);}
int main(){in();ac();}