[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1791
[算法]
不难看出,要求的是这个基环树森林中每棵基环树的直径之和
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 10; struct edge { int to,w,nxt; } e[MAXN << 1]; int i,v,w,tot,n,u,cnt; int degree[MAXN],belong[MAXN],head[MAXN]; long long d[MAXN],f[MAXN],a[MAXN << 1],sum[MAXN << 1]; long long ans; bool cal[MAXN]; inline void addedge(int u,int v,int w) { tot++; e[tot] = (edge){v,w,head[u]}; head[u] = tot; } inline void bfs(int u,int t) { int i,cur,v,w; queue< int > q; belong[u] = t; q.push(u); while (!q.empty()) { cur = q.front(); q.pop(); for (i = head[cur]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!belong[v]) { belong[v] = t; q.push(v); } } } } inline void topsort() { int i,u,v,w; queue< int > q; for (i = 1; i <= n; i++) { if (degree[i] == 1) q.push(i); } while (!q.empty()) { u = q.front(); q.pop(); for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (degree[v] > 1) { d[belong[u]] = max(d[belong[u]],f[u] + f[v] + w); f[v] = max(f[v],f[u] + w); if ((--degree[v]) == 1) q.push(v); } } } } inline void dp(int t,int x) { long long i,l,r,y = x,m = 0,v,w; static int q[MAXN << 1]; do { a[++m] = f[y]; degree[y] = 1; for (i = head[y]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (degree[v] > 1) { y = v; sum[m + 1] = sum[m] + w; break; } } } while(i); if (m == 2) { l = 0; for (i = head[y]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (v == x) l = max(l,w); } d[t] = max(d[t],f[x] + f[y] + l); return; } for (i = head[y]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (v == x) { sum[m + 1] = sum[m] + w; break; } } for (i = 1; i < m; i++) { a[m + i] = a[i]; sum[m + i] = sum[m + 1] + sum[i]; } q[l = r = 1] = 1; for (i = 2; i <= 2 * m - 1; i++) { while (l <= r && i - q[l] >= m) l++; d[t] = max(d[t],a[q[l]] + a[i] + sum[i] - sum[q[l]]); while (l <= r && a[q[r]] - sum[q[r]] <= a[i] - sum[i]) r--; q[++r] = i; } } int main() { scanf("%d",&n); for (u = 1; u <= n; u++) { scanf("%d%d",&v,&w); addedge(u,v,w); addedge(v,u,w); degree[u]++; degree[v]++; } for (i = 1; i <= n; i++) { if (!belong[i]) bfs(i,++cnt); } topsort(); for (i = 1; i <= n; i++) { if (degree[i] > 1 && !cal[belong[i]]) { cal[belong[i]] = true; dp(belong[i],i); ans += d[belong[i]]; } } printf("%lld ",ans); return 0; }