首页 > 其他 > 详细

bzoj1123:[POI2008]BLO

时间:2019-02-17 13:12:52      阅读:275      评论:0      收藏:0      [点我收藏+]

传送门

提示:被删掉的点也要算点对,\((i,j)\)\((j,i)\)是不同的点对

显然找出割点就行了,记下size,对于各子树统计一下答案
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=1e5+10;
int n,m,size[maxn],tot,now,pre[maxn*10],nxt[maxn*10],rt,h[maxn],cnt,dfn[maxn],low[maxn],id;bool cur[maxn],vis[maxn];
long long ans[maxn];
void add(int x,int y)
{
    pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,
    pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt;
}
void tarjan(int x)
{
    dfn[x]=low[x]=++id,size[x]=1;int sum=0,flag=0;
    for(rg int i=h[x];i;i=nxt[i])
    {
        if(!dfn[pre[i]])
        {
            tarjan(pre[i]),size[x]+=size[pre[i]],low[x]=min(low[pre[i]],low[x]);
            if(low[pre[i]]>=dfn[x])
            {
                flag++,sum+=size[pre[i]];
                ans[x]+=1ll*size[pre[i]]*(n-size[pre[i]]);
                if(x!=rt||flag>1)cur[x]=1;
            }
        }
        else low[x]=min(low[x],dfn[pre[i]]);
    }
    if(cur[x])ans[x]+=1ll*(n-sum-1)*(sum+1)+n-1;
    else ans[x]=2*n-2;
}
int main()
{
    read(n),read(m);
    for(rg int i=1,x,y;i<=m;i++)read(x),read(y),add(x,y);
    for(rg int i=1;i<=n;i++)if(!dfn[i])rt=i,tarjan(i);
    for(rg int i=1;i<=n;i++)printf("%lld\n",ans[i]);
}

bzoj1123:[POI2008]BLO

原文:https://www.cnblogs.com/lcxer/p/10390577.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!