迷宫花坛

迷宫花坛

题解:

代码

#include<bits/stdc++.h>
using namespace std;  
int const N=1e5+10;  
int const M=2e5+10;  
struct edge{
	int to,nt,w;  
}e[M<<1],e2[M<<1];   
int n,h[N],cnt,bl[N],q,f[N][17],m,st[N],top,lt[N],dist[N][17],num,rt[N],vis[N],id[N],cnt2,h2[N]; 
int tin[N],tout[N],sum;  
vector<int> cycle[N],se[N];  
map<pair<int,int>,int > mat;  
map<pair<int,int>,int > :: iterator p;  
void add(int a,int b,int c){
	e[++cnt].to=b;  
	e[cnt].w=c;  
	e[cnt].nt=h[a];  
	h[a]=cnt;  
}  
void add2(int a,int b,int c){
	e2[++cnt2].to=b; 
	e2[cnt2].w=c;  
	e2[cnt2].nt=h2[a];  
	h2[a]=cnt2++;  
}
void dfs(int x,int fa,int d){        
	st[++top]=x;  
	lt[top]=d;    
	vis[x]=1;  
	for(int i=h[x];i;i=e[i].nt){
		int v=e[i].to;  
		if(v==fa) continue;  
		if(vis[v] && !bl[v]){
			num++;int k=0,tp=top; 
			rt[num]=v;  
			lt[top+1]=e[i].w;  
			int c=0;  
			while (1){
				int t=st[top];  
				bl[t]=num;  
				id[t]=k; 
				int last=0;      
				if(k) last=cycle[num][k-1];  
				cycle[num].push_back(last+lt[top+1]); 
				se[num].push_back(t);   
				top--;  
				k++;  
				if(t==v) break;   
			}
			top=tp; 
		}else if(!vis[v]) dfs(v,x,e[i].w);  
	}  
	if(!bl[x]) {
		num++; 
		bl[x]=num;  
		id[x]=0;   
		rt[num]=x; 
		se[num].push_back(x);   
		cycle[num].push_back(0);  
	} 
	top--;  
}  
void dfs2(int x,int fa,int d){
	f[x][0]=fa;  
	dist[x][0]=d;  
	tin[x]=++sum;  
	for(int i=h2[x];i;i=e2[i].nt){
		int v=e2[i].to;  
		if(v==fa) continue;  
		dfs2(v,x,e2[i].w);  
	}
	tout[x]=++sum;  
}  
int ancestor(int x,int y){
	return tin[x]<=tin[y] && tout[y]<=tout[x];  
} 
int lca(int x,int y){
	for(int i=16;i>=0;i--)  
		if(!ancestor(f[x][i],y))  
			x=f[x][i];  
	return x; 
} 
int calc(int x,int y){
	if(x==y) return 0; 
	int res=0;  
	for(int i=16;i>=0;i--)
		if(!ancestor(f[x][i],y)){
			res+=dist[x][i];  
			x=f[x][i]; 
		}
	return res+dist[x][0]; 
}  
int main(){
	freopen("garden.in","r",stdin);  
	freopen("garden.out","w",stdout);  
	scanf("%d%d",&n,&m) ; 
	while (m--){
		int x,y,z;  
		scanf("%d%d%d",&x,&y,&z); 
		if(x>y) swap(x,y);  
		if(mat.find(make_pair(x,y))==mat.end()) 
			mat[make_pair(x,y)]=z;   
		else mat[make_pair(x,y)]=min(mat[make_pair(x,y)],z);   
	}
	for(p=mat.begin();p!=mat.end();p++){
		int x=p->first.first; 
		int y=p->first.second;  
		int z=p->second;  
		add(x,y,z); 
		add(y,x,z); 
	}
	dfs(1,1,0);  
	for(int i=1;i<=n;i++) 
		for(int j=h[i];j;j=e[j].nt){
			int x=i; 
			int y=e[j].to;  
			if(bl[x]!=bl[y]) add2(x,y,e[j].w); 
		}
	for(int i=1;i<=num;i++)  
		for(int j=0;j<se[i].size();j++) {
			int x=rt[bl[se[i][j]]];  
			int y=se[i][j]; 
			if(x==y) continue; 
			int z=bl[se[i][j]];       
			int sz=cycle[z].size()-1;
			int d=min(abs(cycle[z][id[x]]-cycle[z][id[y]]),cycle[z][sz]-abs(cycle[z][id[x]]-cycle[z][id[y]])); 
			add2(x,y,d);  
			add2(y,x,d);  
			
		}  
	dfs2(1,1,0); 
	for(int j=1;j<=16;j++)  
		for(int i=1;i<=n;i++){
			f[i][j]=f[f[i][j-1]][j-1]; 
			dist[i][j]=dist[i][j-1]+dist[f[i][j-1]][j-1];  
		} 
	scanf("%d",&q);  
	while (q--){
		int x,y;  
		scanf("%d%d",&x,&y); 
		if(ancestor(x,y))
			printf("%d\n",calc(y,x)); 
		else if(ancestor(y,x))
			printf("%d\n",calc(x,y));  
		else {
			int t1=lca(x,y);  
			int t2=lca(y,x);   
			if(bl[t1]!=bl[t2])  
				printf("%d\n",calc(x,f[t1][0])+calc(y,f[t1][0]));  
			else  {
				int tmp=calc(x,t1)+calc(y,t2);  
				int z=bl[t1];  
				int a=id[t1];  
				int b=id[t2];  
				int sz=cycle[z].size()-1;  
				tmp+=min(abs(cycle[z][a]-cycle[z][b]),cycle[z][sz]-abs(cycle[z][a]-cycle[z][b]));  
				printf("%d\n",tmp); 
			}
		}
	}
	return 0; 
} 
posted @ 2020-08-15 16:37  zjxxcn  阅读(113)  评论(0编辑  收藏  举报