UOJ87题解

迫真虚仙人掌

题意相当于求虚仙人掌的直径,但是我们只要知道了这颗仙人掌的圆方树就够了。

目标变成求虚圆方树。然后发现就是在圆方树上面跑一个虚树。如果一个环上同时出现了两个点就把这个环的方点也加到虚树里面去。

然后没了。

#include<algorithm>
#include<utility>
#include<cstdio>
#include<cctype>
#include<vector>
#include<map>
typedef long long ll;
const int M=3e5+5;
int n,m;int dfc,tot,V[M],fa[M],low[M],dfn[M];
int cnt,h[M<<1],f[M<<1],d[M<<1],siz[M<<1],son[M<<1],top[M<<1],DFN[M<<1];ll S[M<<1],sum[M<<1];
int tp,stk[M<<1];std::map<std::pair<int,int>,int>graph;bool vis[M<<1];
struct edge{
	int v,w;
};std::vector<edge>G[M];
struct Edge{
	int v,nx;ll w;
}e[M<<1];
inline void Add(const int&u,const int&v,const ll&w){
	e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;
}
inline int min(const int&a,const int&b){
	return a>b?b:a;
}
inline ll minll(const ll&a,const ll&b){
	return a>b?b:a;
}
inline ll max(const ll&a,const ll&b){
	return a>b?a:b;
}
inline void Build(const int&u,int v,ll Sum){
	for(int x=v;x^u;x=fa[x])sum[x]=Sum,Sum+=V[x];
	sum[++tot]=Sum;sum[u]=0;Add(u,tot,minll(sum[u],sum[tot]-sum[u]));
	for(int x=v;x^u;x=fa[x])Sum+=V[x],Add(tot,x,minll(sum[x],sum[tot]-sum[x]));
}
inline void Tarjan(const int&u){
	dfn[u]=low[u]=++dfc;
	for(edge&E:G[u])if(E.v^fa[u]){
		const int&v=E.v;
		if(!dfn[v])fa[v]=u,V[v]=E.w,Tarjan(v),low[u]=min(low[u],low[v]);
		else low[u]=min(low[u],dfn[v]);
		if(dfn[u]<low[v])Add(u,v,E.w);
	}
	for(edge&E:G[u])if(fa[E.v]^u&&dfn[u]<dfn[E.v])Build(u,E.v,E.w);
}
inline void DFS1(const int&u){
	siz[u]=1;d[u]=d[f[u]]+1;DFN[u]=++dfc;
	for(int v,E=h[u];E;E=e[E].nx)if((v=e[E].v)^f[u]){
		f[v]=u;S[v]=S[u]+e[E].w;DFS1(v);siz[u]+=siz[v];siz[v]>siz[son[u]]&&(son[u]=v);
	}
}
inline void DFS2(const int&u,const int&tp){
	top[u]=tp;if(!son[u])return;DFS2(son[u],tp);
	for(int E=h[u];E;E=e[E].nx)if(e[E].v^f[u]&&e[E].v^son[u])DFS2(e[E].v,e[E].v);
}
inline int LCA(int u,int v){
	while(top[u]^top[v])d[top[u]]>d[top[v]]?u=f[top[u]]:v=f[top[v]];return d[u]>d[v]?v:u;
}
inline int Find(int u,const int&v){
	while(top[u]^top[v])if(f[top[u]]==v)return top[u];else u=f[top[u]];return son[v];
}
int a,b,p[M<<1];ll ans,t[M<<1];
inline void Solve(const int&u,const int&fa){
	static ll t[M<<1],g[M<<1];static int m,L,R,q[M<<1],id[M<<1];L=1;R=0;m=0;
	for(int v,E=h[u];E;E=e[E].nx)if((v=e[E].v)^fa)id[++m]=v;
	std::sort(id+1,id+m+1,[&](const int&x,const int&y){return sum[x]<sum[y];});
	for(int i=1;i<=m;++i)t[i]=::t[id[i]],g[i]=sum[id[i]];if(fa)g[++m]=sum[u],t[m]=0;
	for(int i=1;i<=(m<<1);++i)g[i+m]=g[i]+sum[u],t[i+m]=t[i];
	for(int i=1;i<=(m<<1);++i){
		while(L<=R&&g[q[L]]+(sum[u]>>1)<g[i])++L;if(L<=R)ans=max(ans,t[i]+t[q[L]]+g[i]-g[q[L]]);
		while(L<=R&&t[q[R]]-g[q[R]]<=t[i]-g[i])--R;q[++R]=i;
	}
	for(int i=1;i<=m;++i)if(t[i]+minll(g[i],sum[u]-g[i])>::t[u])::t[u]=t[i]+minll(g[i],sum[u]-g[i]);
}
inline void DFS(const int&u,const int&fa){
	for(int v,E=h[u];E;E=e[E].nx)if((v=e[E].v)^f[u]){
		DFS(v,u);const ll&V=t[v]+e[E].w;if(u<=n)ans=max(ans,t[u]+V);if(V>t[u])t[u]=V;
	}
	if(u>n)Solve(u,fa);
	for(int E=h[u];E;E=e[E].nx)if(e[E].v^f[u])t[e[E].v]=h[e[E].v]=0;
}
inline void Insert(const int&u){
	if(!tp)return void(stk[tp=1]=u);
	const int&v=LCA(u,stk[tp]);while(tp>1&&d[stk[tp-1]]>d[v])Add(stk[tp-1],stk[tp],S[stk[tp]]-S[stk[tp-1]]),--tp;
	if(d[stk[tp]]>d[v])Add(v,stk[tp],S[stk[tp]]-S[v]),--tp;if(!tp||stk[tp]^v)stk[++tp]=v;if(stk[tp]^u)stk[++tp]=u;
}
inline bool cmp(const int&u,const int&v){
	return DFN[u]<DFN[v];
}
inline ll Solve(){
	std::sort(p+1,p+a+1,cmp);a=std::unique(p+1,p+a+1)-p-1;
	for(int i=1;i<=a;++i)Insert(p[i]);while(tp>1)Add(stk[tp-1],stk[tp],S[stk[tp]]-S[stk[tp-1]]),--tp;
	return ans=0,DFS(stk[tp--],0),t[stk[1]]=h[stk[1]]=0,ans;
}
inline void insert(const int&u,const int&v){
	const int&lca=LCA(u,v);
	if(lca>n){
		const int&ls=Find(u,lca),&rs=Find(v,lca);
		if(ls^u)p[++b]=ls;if(rs^v)p[++b]=rs;
	}
}
inline int read(){
	int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
signed main(){
	n=read();m=read();tot=n;
	for(int u,v,w,i=1;i<=m;++i){
		u=read();v=read();w=read();
		int&a=graph[std::make_pair(u,v)],&b=graph[std::make_pair(v,u)];
		if(!a||a>w)a=w;if(!b||b>w)b=w;
	}
	for(std::pair<std::pair<int,int>,int>E:graph)G[E.first.first].push_back((edge){E.first.second,E.second});
	Tarjan(1);DFS1(1);DFS2(1,1);for(int u=1;u<=tot;++u)h[u]=0;
	m=read();
	while(m--){
		b=a=read();cnt=0;
		for(int i=1;i<=a;++i)p[i]=read();
		std::sort(p+1,p+a+1,cmp);a=std::unique(p+1,p+a+1)-p-1;
		for(int i=1;i<a;++i)insert(p[i],p[i+1]);for(int i=1;i<=a;++i)vis[p[i]]=true;
		for(int i=1;i<=a;++i)if(f[p[i]]>n&&!vis[f[p[i]]]&&vis[f[f[p[i]]]])vis[p[++b]=f[p[i]]]=true;a=b;
		for(int i=1;i<=a;++i)vis[p[i]]=false;printf("%lld\n",Solve());
	}
}
posted @ 2022-04-07 16:18  Prean  阅读(25)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};