蓝书有误
  • 板块学术版
  • 楼主xiaozhangma
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/10/15 09:35
  • 上次更新2023/11/2 13:44:44
查看原帖
蓝书有误
47911
xiaozhangma楼主2023/10/15 09:35

版本:2022年11月第1版

页码:436

相关算法: tarjan 割点

相关题目:link

一个简单的例子:

输出显然为4 4 4,而书上代码输出为6 4 4。

(就是没特判根节点就计算了贡献,具体见代码)

//code by xiaozhangma
#include<bits/stdc++.h>
#define LL long long
#define F(x,s,t) for(int x=s;x<=t;x++)
using namespace std;
int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int x){
	if(x < 0)putchar('-'),x = -x;
	if(x > 9)write(x / 10);
	putchar(x % 10 + '0');
}
const int N = 1e5 + 10, M = 5e5 + 10;
int head[N], ver[M << 1], nx[M << 1];
int dfn[N], low[N], size[N];
int n, m, tot, num;
LL ans[N];
bool cut[N];
void add(int x, int y){
	ver[++tot] = y, nx[tot] = head[x], head[x] = tot;
}
void tarjan(int x){
	dfn[x] = low[x] = ++num, size[x] = 1;
	int flag = 0, sum = 0;
	for(int i = head[x]; i; i = nx[i]){
		int y = ver[i];
		if(!dfn[y]){
			tarjan(y);
			size[x] += size[y];
			low[x] = min(low[x], low[y]);
			if(low[y] >= dfn[x]){
				flag ++ ;
				/*
				ans[x] += 1ll * size[y] * (n - size[y]);
				if( x != 1 || flag > 1)cut[x] = true;
				注释内为书上代码 
				*/
				if( x != 1 || flag > 1){
					sum += size[y];
					cut[x] = true;
					ans[x] += 1ll * size[y] * (n - size[y]);
				}//正解 
			}
		}else{
			low[x] = min(low[x], dfn[y]);
		}
	}
	if(cut[x]){
		ans[x] += 1ll * (n - sum - 1) * (sum + 1) + (n - 1);
	}else{
		ans[x] += 2 * (n - 1);
	}
}
int main(){
	n = read(), m = read();
	tot = 1;
	F(i, 1, m){
		int x = read(), y = read();
		if(x == y)continue;
		add(x, y), add(y, x);
	}
	tarjan(1);
 
	F(i, 1, n){
		printf("%lld\n", ans[i]);
	}
	return 0;
}
/*
input:
3 3
1 2 
2 3 
1 3
output:
4
4 
4
*/

会用github的大佬可以去[这里]勘误(https://github.com/lydrainbowcat/tedukuri)

2023/10/15 09:35
加载中...