记录编号 471445 评测结果 AAAAAAAAAA
题目名称 [NOIP 2013]货车运输 最终得分 100
用户昵称 Gravatarsnake 是否通过 通过
代码语言 C++ 运行时间 0.098 s
提交时间 2017-11-06 14:38:57 内存使用 2.69 MiB
显示代码纯文本
//#include<iostream>
#include<cstring>
#include<climits>
#include<ctime>
#include<fstream>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
using namespace std;
ifstream cin("truck.in");ofstream cout("truck.out");

const int MAX=10010,MAX2=20;
vector<int> map[MAX];	//map[i] 由点i连接出去的所有'边' 
struct edge
{
	int dis;
	int x;
	int y;
	
	bool operator < (const edge& b)const
	{
		return this->dis>b.dis;
	}
};

struct edge2
{
	int dis;
	int target;
};

edge e[MAX*5];	//边 
edge2 f[MAX];	//生成树
edge2 minn[MAX][MAX2];	//minn[i][j]:从i点开始向上2^j个点所经过的边中最小的许可载重(也就是最大可行载重) 
int d[MAX];
bool visited[MAX];
//bool built[MAX];	//built[i]表示并查集祖先为i的集合是否完成了树的构建 (似乎用不着) 

inline int freelog(int n,int a){return int(log2(n)/log2(a));}

//并查集部分↓

int fa[MAX];	//并查集祖先 

void initialization(int n)
{
	for(int i=1;i<=n;i++) fa[i]=i;
	return;
}

int find(int a)
{
	if(fa[a]!=a) fa[a]=find(fa[a]);
	return fa[a];
}

void join(int a,int b)
{
	int aa=find(a);
	int bb=find(b);
	if(aa!=bb) fa[aa]=bb;
	return;
}

bool found(int a,int b)	//return true if a and b had been connected
{
	return find(a)==find(b);
}

//↑并查集部分	树构造函数↓

void create(int t,int de)
{
	d[t]=de;
	visited[t]=1;	//已访问过 
	for(unsigned int i=0;i<map[t].size();i++)
	{
		if((e[map[t][i]].x==t && e[map[t][i]].y==f[t].target) || (e[map[t][i]].x==f[t].target && e[map[t][i]].y==t)) continue;
		int temp=(e[map[t][i]].x==t?e[map[t][i]].y:e[map[t][i]].x);
		f[temp].target=t;
		f[temp].dis=e[map[t][i]].dis;
		create(temp,de+1);
	}
	return;
}

//↑树构造函数	 问题求解↓

int answer(int x,int y)
{
	if(!found(x,y)) return -1;	//no answer
	if(d[x]<d[y]) swap(x,y);
	
	int minx=INT_MAX,miny=INT_MAX;
	
	while(d[x]>d[y])
	{
		int c=freelog(d[x]-d[y],2);
		minx=min(minx,minn[x][c].dis);
		x=minn[x][c].target;
	}
	if(x==y) return minx;
	
	for(int i=freelog(d[x],2);i>=0;i--)
	{
		if(minn[x][i].target!=minn[y][i].target && minn[x][i].target!=0 && minn[y][i].target!=0)
		{
			minx=min(minx,minn[x][i].dis);
			miny=min(miny,minn[y][i].dis);
			
			x=minn[x][i].target;
			y=minn[y][i].target;
		}
	}
	
	minx=min(minx,minn[x][0].dis);
	miny=min(miny,minn[y][0].dis);
	
	return min(minx,miny);
}

//↑问题求解 

int main()
{
	//输入部分↓(checked)
	
	ios::sync_with_stdio(false);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++) cin>>e[i].x>>e[i].y>>e[i].dis;
	
	//↑输入部分(checked) 最大生成树↓(checked)
	
	initialization(n);
	sort(e+1,e+m+1);
	 int maxx=INT_MIN,maxp;
	for(int i=1;i<=m;i++)
	{
		if(!found(e[i].x,e[i].y))
		{
			int x=e[i].x,y=e[i].y;
			join(x,y);
			map[x].push_back(i);
			map[y].push_back(i);
			if(map[x].size()>=map[y].size() && int(map[x].size())>maxx)
			{
				maxx=map[x].size();
				maxp=x;
			}else if(int(map[y].size())>maxx){
				maxx=map[y].size();
				maxp=y;
			}
		}
	}
	
	//↑最大生成树(checked)	构造树↓(checked) 
	
	f[maxp].target=0;
	f[maxp].dis=0;
	//built[find(maxp)]=1;
	create(maxp,1);
	for(int i=1;i<=n;i++)
	{
		if(!visited[i])
		{
			f[i].dis=0;
			f[i].target=0;
			//built[find(i)]=1;
			create(i,1);
		}
	}
	
	//↑构造树(checked)	路径倍增↓
	
	for(int i=1;i<=n;i++)
	{
		minn[i][0].dis=f[i].dis;
		minn[i][0].target=f[i].target;
	}
	
	for(int j=1;j<MAX2;j++) for(int i=1;i<=n;i++)
	{
		if(minn[i][j-1].target!=-1)
		{
			minn[i][j].dis=min(minn[i][j-1].dis,minn[minn[i][j-1].target][j-1].dis);
			minn[i][j].target=minn[minn[i][j-1].target][j-1].target;
		}
	}
	
	/***********************************************************-*测试*-***********************************************************
	*cout<<endl;
	*for(int i=1;i<=n;i++)
	*{
	*	cout<<i<<endl;
	*	for(int j=0;j<MAX2;j++) cout<<j<<" "<<minn[i][j].target<<" "<<minn[i][j].dis<<endl;
	*	cout<<endl<<endl;
	*}
	*cout<<endl;
	************************************************************-*测试*-************************************************************/
	
	//↑路径倍增	问题求解(逻辑)↓ 
	
	int q;
	cin>>q;
	for(int i=1;i<=q;i++)
	{
		int x,y;
		cin>>x>>y;
		cout<<answer(x,y)<<endl;
	}
	
	//↑问题求解(逻辑)
	
	return 0;
}

/*
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
*/