1. 程式人生 > >最小生成樹和倍增法求lca(Uva11354Bond)

最小生成樹和倍增法求lca(Uva11354Bond)

#include<bits/stdc++.h>
#define maxn 600000
#define inf (1124984)
using namespace std;
int head[maxn],book[maxn],deep[maxn],pre[maxn],fa[maxn],mxcost[maxn][30],cost[maxn],p[maxn][30];
int n,m,k,cnt=0;
struct Edge{int from,to,w;}e[maxn];
struct Edg{int to,next,w;}edge[maxn];
int find(int x){return x==pre[x]?x:pre[x]=find(pre[x]);}//並查集 
bool cmp(Edge a,Edge b){return a.w<b.w;}
void add(int u,int v,int w)
{
	edge[++cnt].to=v;
	edge[cnt].next=head[u];
	head[u]=cnt;
	edge[cnt].w=w;
}

void MinTree()//最小生成樹,克魯斯卡爾名字不會打了,就。。 
{
	for(int i=1;i<=n;i++) pre[i]=i;
	sort(e+1,e+m+1,cmp);
	int num=0;
	for(int i=1;i<=m;i++)
	{
		int fx=find(e[i].from),fy=find(e[i].to);
		if(fx!=fy)
		{
			pre[fx]=fy;
			num++;
			add(e[i].from,e[i].to,e[i].w);
			add(e[i].to,e[i].from,e[i].w);
			if(num==n-1) break;
		}
	}
}
void DFS(int x)
{
	book[x]=1;
	for(int i=head[x];i;i=edge[i].next)
	{
		int j=edge[i].to;
		if(!book[j])
		{
			fa[j]=x;
			deep[j]=deep[x]+1;
			cost[j]=edge[i].w;
			DFS(j);
		}
	}
}

void preprocess()
{
	for(int i=1;i<=n;i++)
	{
		p[i][0]=fa[i];mxcost[i][0]=cost[i];
		for(int j=1;(1<<j)<=n;j++) p[i][j]=-1;//沒有父親的節點初始化為-1 
	}
	for(int j=1;(1<<j)<=n;j++)
		for(int i=1;i<=n;i++)
		{
			int fat=p[i][j-1];
			if(fat!=-1)
			{
				p[i][j]=p[fat][j-1];
				mxcost[i][j]=max(mxcost[i][j-1],mxcost[fat][j-1]);//最大的邊權等於這個點到他的2^j-1和2^j-1到2^j的最大邊權 
			}
		}
/*	for(int j=1;(1<<j)<=n;j++)
		for(int i=1;i<=n;i++)
			cout<<mxcost[i][j]<<"~"<<i<<j<<"\n";*/
}

int query(int a,int b)//套用lca的模板 
{
	if(deep[a]<deep[b]) swap(a,b);
	int i=0,ans=0;
	while((1<<i)<=n) i++;
	i--;//減小邊界為2^i-1 
	int depth=deep[a]-deep[b];
	for(int j=i;j>=0;j--)
		if((1<<j)&depth) 
		{ans=max(ans,mxcost[a][j]);a=p[a][j];}//注意更新的順序 
	if(b==a) return ans;
	for(int j=i;j>=0;j--)
	{
		if(p[a][j]!=p[b][j])
		{
			ans=max(ans,mxcost[a][j]);
			ans=max(ans,mxcost[b][j]);
			a=p[a][j],b=p[b][j];	
		}
	}
	ans=max(ans,mxcost[a][0]);
	ans=max(ans,mxcost[b][0]);
	return ans;
}
//一定要初始化 
void init()
{
	memset(e,0,sizeof(e));
	memset(edge,0,sizeof(edge));
	memset(book,0,sizeof(book));
	memset(deep,0,sizeof(deep));
	memset(fa,0,sizeof(fa));
	memset(head,0,sizeof(head));
	memset(mxcost,0,sizeof(mxcost));
	memset(cost,0,sizeof(cost));
	cnt=0;
}

int main()
{
	int kase=0;
	while(cin>>n>>m)
	{
		init();
		for(int i=1;i<=m;i++)
			cin>>e[i].from>>e[i].to>>e[i].w;
		MinTree();
		deep[1]=1;fa[1]=-1;
		DFS(1);
		/*for(int i=1;i<=4;i++)
			cout<<deep[i]<<"~"<<i<<"\n";*/
		preprocess(); 
		int k;cin>>k;
		if(++kase!=1) cout<<"\n";
		while(k--)
		{
			int t1,t2;
			cin>>t1>>t2;
			cout<<query(t1,t2)<<"\n";
		}
	}
	return 0;
}