版权声明:_ https://blog.csdn.net/lunch__/article/details/81837308
学了圆方树后做的第二个题…
感觉圆方树的精髓就是在魔改方点上面啊…
这个题我们首先构建出一颗圆方树
把方点权值设为整个点双的点数
但是圆点存在的基础上可能会多算
所以我们把圆点权值赋为
直接统计路径数就好了
算答案的时候如果是圆点就考虑经过它包括它作为起点的路径
方点就不考虑它作为起点只考虑穿过它的路径即可
Codes
#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
int read() {
int _ = 0, ___ = 1; char __ = getchar();
for(; !isdigit(__); __ = getchar()) if(__ == '-') ___ = -1;
for(; isdigit(__); __ = getchar()) _ = (_ << 3) + (_ << 1) + (__ ^ 48);
return ___ * _;
}
const int N = 2e5 + 10, M = 4e5 + 10;
int to[M], head[N], nxt[M], e;
vector<int> kuai[N], G[N];
int n, m, color, val[N], ans;
int size[N], vis[N], all;
void add(int x, int y) {
to[++ e] = y; nxt[e] = head[x]; head[x] = e;
}
namespace Tarjan {
int dfn[N], low[N], cnt, Sta[N], top;
void dfs(int x, int fa) {
dfn[x] = low[x] = ++ cnt; Sta[++ top] = x;
for(int j = 0, sz = G[x].size(); j < sz; ++ j) {
if(!dfn[G[x][j]]) {
dfs(G[x][j], x);
low[x] = min(low[x], low[G[x][j]]);
if(low[G[x][j]] >= dfn[x]) {
++ color;
do {
kuai[color].pb(Sta[top]);
}while(G[x][j] != Sta[top --]);
kuai[color].pb(x);
}
}
else if(G[x][j] != fa)
low[x] = min(low[x], dfn[G[x][j]]);
}
}
}
void dfs(int x) {
//cerr << x << endl;
vis[x] = 1; all += (size[x] = (x <= n));
for(int i = head[x]; i; i = nxt[i])
if(!vis[to[i]]) {
dfs(to[i]);
size[x] += size[to[i]];
}
}
void cal(int x, int fa) {
if(x <= n) ans += val[x] * (size[x] * (all - size[x] + 1) - 1) << 1;
else ans += val[x] * (size[x] * (all - size[x])) << 1;
//ans += (size[x] - 1) * (all - size[x]) * val[x] * 2;
//if(fa && x <= n) ans += (all - size[x] - 1) * val[x] * 2;
for(int i = head[x]; i; i = nxt[i])
if(to[i] != fa) {
cal(to[i], x);
if(x > n) ans += (size[x] - size[to[i]]) * size[to[i]] * val[x];
else ans += (size[x] - size[to[i]] - 1) * size[to[i]] * val[x];;
//ans += (size[x] - size[to[i]] - 1) * (size[to[i]]) * val[x];
//if(x <= n) ans += (size[to[i]] - 1) * val[x] * 2;
}
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("2587.in", "r", stdin);
freopen("2587.out", "w", stdout);
#endif
int x, y;
n = read(), m = read();
for(int i = 1; i <= m; ++ i) {
x = read(), y = read();
G[x].pb(y), G[y].pb(x);
}
for(int i = 1; i <= n; ++ i)
if(!Tarjan::dfn[i])
Tarjan::dfs(i, 0);
memset(val, -1, sizeof val);
for(int i = 1; i <= color; ++ i) {
val[i + n] = kuai[i].size();
for(int j = 0, sz = kuai[i].size(); j < sz; ++ j) {
//val[i + n] -= (val[kuai[i][j]] = -1);
val[kuai[i][j]] = -1;
add(i + n, kuai[i][j]), add(kuai[i][j], i + n);
}
}
for(int i = 1; i <= n; ++ i)
if(!vis[i])
all = 0, dfs(i), cal(i, 0);
printf("%lld\n", ans);
return 0;
}