圆方树orz,参见猫的课件(apio和wc的)以及这里那里

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, uu, vv, oea[100005], loo[100005], dfn[100005], idx, sta[100005];
int siz[200005], val[200005], tot, sze, din, ont, cnt, hea[200005];
ll ans;
struct Edge{
	int too, nxt;
}odge[400005], edge[400005];
void add_odge(int fro, int too){
	odge[++ont].nxt = oea[fro];
	odge[ont].too = too;
	oea[fro] = ont;
}
void add_edge(int fro, int too){
	edge[++cnt].nxt = hea[fro];
	edge[cnt].too = too;
	hea[fro] = cnt;
}
void tarjan(int x){
	dfn[x] = loo[x] = ++idx;
	sta[++din] = x;
	siz[x] = 1;
	val[x] = -1;
	for(int i=oea[x]; i; i=odge[i].nxt){
		int t=odge[i].too;
		if(!dfn[t]){
			tarjan(t);
			loo[x] = min(loo[x], loo[t]);
			if(loo[t]>=dfn[x]){
				int p;
				tot++;
				add_edge(x, tot);
				do{
					p = sta[din--];
					val[tot]++;
					add_edge(tot, p);
					siz[tot] += siz[p];
				}while(p!=t);
				val[tot]++; siz[x] += siz[tot];
			}
		}
		else    loo[x] = min(loo[x], dfn[t]);
	}
}
void dfs(int x){
	if(x<=n)	ans += (ll)val[x] * (sze - 1);
	ans += (ll)val[x] * (sze - siz[x]) * siz[x];
	for(int i=hea[x]; i; i=edge[i].nxt){
		int t=edge[i].too;
		dfs(t);
		ans += (ll)val[x] * (sze - siz[t]) * siz[t];
	}
}
int main(){
	cin>>n>>m;
	tot = n;
	for(int i=1; i<=m; i++){
		scanf("%d %d", &uu, &vv);
		add_odge(uu, vv);
		add_odge(vv, uu);
	}
	for(int i=1; i<=n; i++)
		if(!dfn[i]){
			tarjan(i);
			sze = siz[i];
			dfs(i);
		}
	cout<<ans<<endl;
	return 0;
}

相关文章:

  • 2021-11-16
  • 2021-12-24
  • 2021-08-11
  • 2021-05-24
  • 2021-06-14
  • 2022-01-19
  • 2021-10-09
  • 2021-06-14
猜你喜欢
  • 2021-07-08
  • 2022-12-23
  • 2021-08-30
  • 2022-12-23
  • 2021-07-06
  • 2021-11-19
相关资源
相似解决方案