标签:sz 结点 int 题解 ll 城镇 BLO ans BZOJ1123
题目描述
B城有n个城镇。m条双向道路。每条道路连接两个不同的城镇,没有重复的道路,所有城镇连通。
你需要输出n个数,第i个数表示删除结点i关联的边,不删去i结点,有多少个有序对(x,y),满足城镇x和城镇y不连通。
输入
输入n,m及m条边。n<=100000,m<=500000
输出
输出n个数,第i个数表示删除结点i关联的边,不删去i结点,有多少个有序对(x,y),满足城镇x和城镇y不连通。
样例
样例输入1
5 5
1 2
2 3
1 3
3 4
4 5
样例输出1
8
8
16
14
8
代码实现(带注释)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+2,M=5e5+2;
int hd[N],to[N<<1],nxt[N<<1];//图
int dfn[N],low[N],sz[N];
//dfn:时间戳
//low[i]:在[i的子树中以及通过一条不为树上的边能到达子树的点]的时间戳的最小值
//sz[i]:以i为根的子树大小
ll ans[N];
//答案数组
bool cut[N];
int tot,num,n,m,x,y;
void add(int x,int y){
to[++tot]=y;
nxt[tot]=hd[x];
hd[x]=tot;
}//邻接表
void tarjan(int x){
dfn[x]=low[x]=++num;//初始化:时间戳1
sz[x]=1;//初始化子树大小
int fg=0,sum=0;
//fg
for(int i=hd[x];i;i=nxt[i]){
int y=to[i];
if(!dfn[y]){//在树上x是y的baba
tarjan(y);
sz[x]+=sz[y];//维护子树大小数组
low[x]=min(low[x],low[y]);
//y这棵子树都能到
if(low[y]>=dfn[x]){//x是割点
fg++;
ans[x]+=(ll)sz[y]*(n-sz[y]);
sum+=sz[y];
if(x!=1||fg>1) cut[x]=1;//不为根节点 或 为根节点并且有多个子树
}
}else low[x]=min(low[x],dfn[y]);//x,y不是树上的边
//只能到y这一个点
}
if(cut[x]) ans[x]+=(ll)(n-1-sum)*(1+sum)+(n-1); //case 2:yes,you got it
else ans[x]=2*(n-1);//case 1:不是割点
}
int main(){
cin>>n>>m;
while(m--){
cin>>x>>y;
if(x==y) continue;
add(x,y),add(y,x);
}
tarjan(1);
for(int i=1;i<=n;i++){
cout<<ans[i]<<"\n";
}
return 0;
}
标签:sz,结点,int,题解,ll,城镇,BLO,ans,BZOJ1123 来源: https://www.cnblogs.com/Aurora1217/p/16379899.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。