岛屿

求基环树直径

未完成 挖坑

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define ll long long
#define fs first
#define sc second
#define mp make_pair
using namespace std;
const int N=1e6+10;
const int M=N*2;
int read()
{
	int x=0,f=0,c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return f?-x:x;
}

struct Edge
{
	int to,next,w;
}e[M];
int head[N],cnt=1;
void _add(int a,int b,int c){ e[++cnt]=(Edge){b,head[a],c}; head[a]=cnt;}
void add(int a,int b,int c){ _add(a,b,c); _add(b,a,c); }

bool vis[N],onr[N];
int ring[N],tot,top,n;
ll dis[N],ans,ret,a[N*2],sum,d[N];
pair<int,long long> sta[N];

ll getdis(int x,int y)
{
	if(x>y) swap(x,y);
	if(y<=tot) return dis[y]-dis[x];
	return sum-(dis[y-tot]-dis[x]);
}

void dfs(int x,int ine)
{
	sta[++top]=mp(x,e[ine].w); vis[x]=1;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(i==(ine^1)) continue;
		if(!vis[y]) dfs(y,i);
		else 
		{
			int tmp=e[i].w;
			for(int t=sta[top].fs;t!=x;t=sta[--top].fs) 
			{
				onr[t]=1,ring[++tot]=t;
				dis[tot+1]=dis[tot]+sta[top].sc; sum+=sta[top].sc;
			}
			onr[x]=1;ring[++tot]=x;dis[tot+1]=dis[tot]+tmp;sum+=tmp;
		}
	}
	top--; 
}

void dp(int x,int ff)
{
	vis[x]=1;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(onr[y]||y==ff) continue;
		dp(y,x);
		ret=max(ret,d[x]+d[y]+e[i].w);
		d[x]=max(d[x],d[y]+e[i].w);
	}
}

deque<int> q;
int D(int x)
{
	dfs(x,0);
	for(int i=1;i<=tot;i++) dp(ring[i],0);
	for(int i=1;i<=tot;i++) a[i]=a[i+tot]=d[ring[i]];
	q.push_back(1);
	for(int i=2;i<=tot+sum/2;i++)
	{
		while(q.size()&&getdis(ring[i],ring[q.front()])>sum/2) q.pop_front();
		ret=max(ret,a[i]+a[q.front()]+getdis(ring[i],ring[q.front()]));
		while(q.size()&&a[i]-i>a[q.back()]-q.back()) q.pop_back();
	}
	return ret;
}

int main()
{
	n=read();
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read(),z=read();
		add(x,y,z);
	}
	for(int i=1;i<=n;i++)
		if(!vis[i]) ans+=D(i);
	printf("%d",ans);
}
posted @ 2022-01-20 18:39  __iostream  阅读(30)  评论(0)    收藏  举报