【洛谷P3469】[POI2008]BLO-Blockade

BLO-Blockade

题目链接

若一个点为割点:统计出每个子树的大小,两两相乘再相加,

        再加上n-1,为这个点与其他点的拜访数,

        因为拜访是互相的,最后再乘二即可

若一个点不是割点:只有(n-1)*2次拜访会受影响

#include<cstdio>
#define LL long long
#define N 100010
#define M 1000010
#define min(a,b) ((a)<(b)?(a):(b))
int n,m,dfn[N],low[N],size[N],cnt;
LL ans[N];
const int ch_top=4e7+3;
char ch[ch_top],*now_r=ch-1,*now_w=ch-1;
inline int read(){
    while(*++now_r<'0');
    register int x=*now_r-'0';
    while(*++now_r>='0')x=x*10+*now_r-'0';
    return x;
}
inline void write ( LL x ) {
    static char st[20] ; static int top ;
    if ( x < 0 ) *++now_w = '-' , x *= -1 ;
    while( st[++top] = x % 10 ^ 48 , x /= 10 ) ;
    while( *++now_w = st[top] , --top );
    *++now_w = '
' ;
}
int Head[N],num;
struct NODE{
    int to,next;
} e[M];
void Tarjan(int u){
    dfn[u]=low[u]=++cnt;
    size[u]=1; int t=0;
    for(int i=Head[u];i;i=e[i].next){
        int 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)t*size[v];
                t+=size[v];
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
    if(n-t-1>0) ans[u]+=(LL)(n-t-1)*t;
}
int main()
{
    
    fread(ch,1,ch_top,stdin);
    n=read(); m=read();
    int x,y;
    for(int i=1;i<=m;i++){
        x=read(); y=read();
        e[++num].to=y;
        e[num].next=Head[x];
        Head[x]=num;
        e[++num].to=x;
        e[num].next=Head[y];
        Head[y]=num;
    }
    Tarjan(1);
    for(int i=1;i<=n;i++)
        write((ans[i]+n-1)<<1);
    fwrite(ch,1,now_w-ch,stdout);
    return 0;
}
原文地址:https://www.cnblogs.com/yjkhhh/p/9414061.html