[2018.07.21 T3] Booom

暂无链接

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;

扫描二维码关注公众号,回复: 2339850 查看本文章

对100%的输入数据 :N≤100000,M≤500000。

数据非常有梯度。

题解

出题人题解:TIM截图20180721174752.png

然而这么简单的题我还是爆零了,全场暴力写挂,我为什么这么优秀???

考试的时候想把每个割点的所有儿子大小算出来,然而每次只需要算出一个就可以了。

还有一堆人做过原题

我好菜啊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();}

猜你喜欢

转载自blog.csdn.net/shadypi/article/details/81147349
T3