zoukankan      html  css  js  c++  java
  • BZOJ1123: [POI2008]BLO

    BZOJ1123: [POI2008]BLO

    Description

    Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。

    Input

    输入n<=100000 m<=500000及m条边

    Output

    输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。

    Sample Input

    5 5
    1 2
    2 3
    1 3
    3 4
    4 5

    Sample Output

    8
    8
    16
    14
    8

    题解Here!

    首先可以对任意一个节点$i$进行讨论:
    1. 假如$i$不是割点,那么这个图只有$i$是独立在外面的。
    由于求的是有序点对,所以除了$i$以外的$n-1$个点作为一个大的连通图对$i$加边,即为$2 imes(n-1)$对。
    2. 假如$i$是割点,那么会把图分为$x$个连通块以及$i$本身。
    由于$Tarjan$在求割点的过程中是一棵搜索树往下遍历,所以除了它和它的子树外,还会有其他剩余点共同构成另一个连通块。
    设$i$所有子树的和为$w$,第$i$个子树的节点总数为$size[i]$,点对的数量便为:
    $$sum_{i=1}^xsize[i] imes(n-size[x])+(n-1)+(1+w) imes(n-w-1)$$
    所以在求割点的过程中每遇到一个$low[v]>=dfn[u]$便把对数加上$size[i] imes(n-size[i])$。
    最后假如不是割点那直接把对数更新为$2 imes(n-1)$是割点则加上$n-1+(n-w-1) imes(w+1)$。
    最后遍历输出答案即可。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 100010
    using namespace std;
    int n,m,c=1,d=1;
    int head[MAXN],deep[MAXN],low[MAXN],size[MAXN];
    bool cut[MAXN];
    long long ans[MAXN];
    struct Edge{
    	int next,to;
    }a[MAXN*10];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void add_edge(int x,int y){
    	a[c].to=y;a[c].next=head[x];head[x]=c++;
    	a[c].to=x;a[c].next=head[y];head[y]=c++;
    }
    void dfs(int x){
    	int s=0,w=0;
    	deep[x]=low[x]=d++;
    	size[x]=1;
    	for(int i=head[x];i;i=a[i].next){
    		int v=a[i].to;
    		if(!deep[v]){
    			dfs(v);
    			low[x]=min(low[x],low[v]);
    			size[x]+=size[v];
    			if(low[v]>=deep[x]){
    				ans[x]+=1LL*size[v]*(n-size[v]);
    				w+=size[v];
    				s++;
    				if(x!=1||s>=2)cut[x]=true;
    			}
    		}
    		else low[x]=min(low[x],deep[v]);
    	}
    	if(!cut[x])ans[x]=2*(n-1);
    	else ans[x]+=1LL*(n-w-1)*(w+1)+n-1;
    }
    void work(){
    	int x,y;
    	n=read();m=read();
    	for(int i=1;i<=m;i++){
    		x=read();y=read();
    		add_edge(x,y);
    	}
    	dfs(1);
    	for(int i=1;i<=n;i++)printf("%lld
    ",ans[i]);
    }
    int main(){
    	work();
        return 0;
    }
    
  • 相关阅读:
    将js进行到底:node学习1
    mui开发app前言(一)
    用kotlin方式打开《第一行代码:Android》之开发酷欧天气(最终版)
    用kotlin方式打开《第一行代码:Android》之开发酷欧天气(2)
    用kotlin方式打开《第一行代码:Android》之开发酷欧天气(1)
    062、如何使用flannel host-gw backend(2019-04-02 周二)
    061、flannel的连通与隔离(2019-04-01 周一)
    060、在docker中使用flannel(2019-03-29 周五)
    059、安装配置flannel(2019-03-28 周四)
    058、flannel概述(2019-03-27 周三)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9840474.html
Copyright © 2011-2022 走看看