2019.04.01【BZOJ2125】【洛谷P5326】【模板】静态仙人掌(圆方树)

BZOJ传送门

洛谷传送门


补档计划无题解


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const

namespace IO{
	inline char get_char(){
		static cs int Rlen=1<<20|1;
		static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline int getint(){
		re char c;
		while(!isdigit(c=gc()));re int num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
}
using namespace IO;

using std::cout;
using std::cerr;

cs int N=1e4+4;

int n,m,q;

int ext;
namespace Tree{
	static cs int N=::N<<1;
	struct edge{
		int to,w;
		edge(cs int &_to,cs int &_w):to(_to),w(_w){}
	};
	
	std::vector<edge> G[N];
	typedef std::vector<edge>::iterator iter;
	
	inline void addedge(int u,int v,int val){
		G[u].push_back(edge(v,val));
		G[v].push_back(edge(u,val));
	}
	
	int fa[N],dep[N],top[N],siz[N],son[N];
	int dist[N];
	void dfs1(int u){
		siz[u]=1;
		for(iter re e=G[u].begin();e!=G[u].end();++e)if(e->to!=fa[u]){
			dist[e->to]=dist[u]+e->w;
			fa[e->to]=u;
			dep[e->to]=dep[u]+1;
			dfs1(e->to);
			siz[u]+=siz[e->to];
			if(siz[e->to]>siz[son[u]])son[u]=e->to;
		}
	}
	
	void dfs2(int u){
		if(son[u]){
			top[son[u]]=top[u];
			dfs2(son[u]);
		}
		else return ;
		for(iter re e=G[u].begin();e!=G[u].end();++e)if(e->to!=fa[u]&&e->to!=son[u]){
			top[e->to]=e->to;
			dfs2(e->to); 
		}
	}
	
	inline void build(){
		dfs1(1);
		top[1]=1;
		dfs2(1);
	}
	
	inline int LCA(int u,int v){
		while(top[u]!=top[v])dep[top[u]]<dep[top[v]]?(v=fa[top[v]]):(u=fa[top[u]]);
		return dep[u]<dep[v]?u:v;
	}
	
	inline int find(int u,int f){
		int res;
		while(top[u]!=top[f]){
			res=top[u];
			u=fa[top[u]];
		}
		return u==f?res:son[f];
	}
}

namespace Cactu{
	static cs int N=::N;
	struct edge{
		int to,w;
		edge(cs int &_to,cs int &_w):to(_to),w(_w){}
	};
	
	std::vector<edge> G[N];
	typedef std::vector<edge>::iterator iter;
	
	inline void addedge(int u,int v,int val){
		G[u].push_back(edge(v,val));
		G[v].push_back(edge(u,val));
	}
	
	int w[N],sum[N<<1],fa[N];
	int dfn[N],low[N],dfs_clock;
	
	inline void solve(cs int u,cs int v,int val){
		++ext;
		for(int re i=v;i!=fa[u];i=fa[i]){
			sum[i]=val;
			val+=w[i];
		}
		sum[ext]=sum[u];
		sum[u]=0;
		for(int re i=v;i!=fa[u];i=fa[i]){
			int p=std::min(sum[i],sum[ext]-sum[i]);
			Tree::addedge(ext,i,p);
		}
	}
	
	inline void tarjan(int u,int pa){
		dfn[u]=low[u]=++dfs_clock;
		for(iter re e=G[u].begin();e!=G[u].end();++e)if(e->to!=pa){
			int v=e->to;
			if(!dfn[v]){
				fa[v]=u,w[v]=e->w;
				tarjan(v,u);
				low[u]=std::min(low[u],low[v]);
			}
			else low[u]=std::min(low[u],dfn[v]);
			if(low[v]>dfn[u])Tree::addedge(u,v,e->w);
		}
		for(iter re e=G[u].begin();e!=G[u].end();++e)if(fa[e->to]!=u&&dfn[e->to]>dfn[u])solve(u,e->to,e->w);
	}
}

inline int query(int u,int v){
	int lca=Tree::LCA(u,v);
	if(lca<=n)return Tree::dist[u]+Tree::dist[v]-(Tree::dist[lca]<<1);
	int fu=Tree::find(u,lca),fv=Tree::find(v,lca);
	int tmp=abs(Cactu::sum[fu]-Cactu::sum[fv]);
	return Tree::dist[u]+Tree::dist[v]-Tree::dist[fu]-Tree::dist[fv]
	+std::min(tmp,Cactu::sum[lca]-tmp);
}

signed main(){
	ext=n=getint(),m=getint(),q=getint();
	for(int re i=1,u,v,val;i<=m;++i){
		u=getint(),v=getint(),val=getint();
		Cactu::addedge(u,v,val);
	}
	Cactu::tarjan(1,0);
	Tree::build();
	while(q--)cout<<query(getint(),getint())<<"\n";
	return 0;
}
发布了967 篇原创文章 · 获赞 369 · 访问量 7万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览