• P3469 [POI2008]BLO-Blockade


    题目链接

    题解:

    这道题很容易看出是求割点的板子题,但是难点是计算贡献。

    其实手推一下样例就可以发现,如果一个点不是割点的话那么割掉它的贡献就是n-1,因为少了n-1次拜访。

    而如果它是割点怎么办呢?就可以这样做,它的贡献就是它的子树的大小size,子树上有size个点,而断掉它,这size个点的贡献为size*(n-size)。而这个点本身的贡献为n-1,还要算不是它的子树上的点的贡献,一共还剩下n-size-1个点,所以贡献同子树的贡献,也就是(n-size-1)*(size+1)的贡献,最后累加起来求和就可以了。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+7;
    struct node{
        int nxt,to;
    }edge[maxn*2];
    int head[maxn],cnt;
    void add(int x,int y){
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;
        head[x]=cnt;
    }
    int n,m,x,y;
    int dfn[maxn],low[maxn],in;
    bool check[maxn];
    long long ans[maxn];
    long long siz[maxn];
    void tarjan(int x){
        dfn[x]=low[x]=++in;
        siz[x]=1;
        int son=0;
        long long sum=0;
        bool cut=false;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[v],low[x]);
                siz[x]+=siz[v];
                if(low[v]>=dfn[x]){
                    son++;
                    ans[x]+=(long long)siz[v]*(n-siz[v]);
                    sum+=siz[v];
                    if(x!=1||son>=2) cut=true;
                }
            }
            else low[x]=min(dfn[v],low[x]);
        }
        if(!cut) ans[x]=(n-1)*2;
        else ans[x]+=(n-1)+(n-sum-1)*(sum+1); 
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        tarjan(1);
        for(int i=1;i<=n;i++) printf("%lld
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    mysql BETWEEN操作符 语法
    mysql IN操作符 语法
    mysql LIKE通配符 语法
    mysql TOP语句 语法
    mysql DELETE语句 语法
    mysql Update语句 语法
    mysql INSERT语句 语法
    mysql ORDER BY语句 语法
    mysql OR运算符 语法
    mysql AND运算符 语法
  • 原文地址:https://www.cnblogs.com/LJB666/p/11651506.html
Copyright © 2020-2023  润新知