NKOJ 2495 货车运输 【NOIP2013-D1T3】
时间限制 : 10000 MS 空间限制 : 128000 KB
问题描述
A国有n座城市,编号从1到n,城市之间有m条双向道路。
每一条道路对车辆都有重量限制,简称限重。
现在有q辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入格式
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有n座城市和m条道路。
接下来m行,每行3个整数x,y,z,表示从x号城市到y号城市有一条限重为z的道路(x≠y,两座城市之间可能有多条道路)
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来q行,每行两个整数x,y,之间用一个空格隔开,表示一辆货车需要从x城市运输货物到y城市(x≠y)。
输出格式
输出共有 q 行,每行一个整数,表示对于这一辆货车,它的最大载重是多少。
如果货车不能到达目的地,输出-1。
样例输入
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
样例输出
3
-1
3
提示
对于 30%的数据,1<=n<=1000,1<=m<=10000,1<=q<=1000;
对于 60%的数据,1<=n<=1000,1<=m<=50000,1<=q<=1000;
对于 100%的数据,1<=n<=10000,1<=m<=50000,1<=q<=30000,0<=z<=100000。
思路:
重边处理:最大生成树
森林处理:并查集
对于每次询问,并查集查询是否在一颗树上,不在输出-1,在,则LCA。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double log_2=log(2);
const int inf=1e9;
const int needn=10003;
const int needm=50003;
struct fy{int a,b,val;}w[needm];
int s=0,m=0;
int belong[needn],dep[needn],fa[needn][17],val[needn][17];
int la[needn*2],len[needn*2],en[needn*2],fi[needn];
bool visit[needn],use[needn];
//...................................................................
inline void in_(int &d)
{
bool mark=false;char t=getchar();
while(t<'0'||t>'9'){if(t=='-') mark=true;t=getchar();}
for(d=0;t>='0'&&t<='9';t=getchar())d=(d<<3)+(d<<1)-'0'+t;
if(mark)d=-d;
}
char o[100];
inline void out_(int x)
{
int l=1;
if(x<0) x=-x,putchar('-');
if(!x) putchar('0');
for(;x;x/=10) o[l++]=x%10+'0';
for(l--;l;l--)putchar(o[l]);
putchar('\n');
}
//...................................................................
void add(int a,int b,int c)
{
m++;
en[m]=b;
len[m]=c;
la[m]=fi[a];
fi[a]=m;
}
//...................................................................
int getbelong(int x)
{
return x==belong[x]?x:belong[x]=getbelong(belong[x]);
}
//...................................................................
bool way(fy x,fy y)
{
return x.val>y.val;
}
//...................................................................
void dfs(int x)
{
int k=ceil(log(dep[x])/log_2);
s=max(s,k);
for(int i=1;i<=k;i++)
{
fa[x][i]=fa[fa[x][i-1]][i-1];
val[x][i]=min(val[x][i-1],val[fa[x][i-1]][i-1]);
}
int t=fi[x],y;
while(t)
{
y=en[t];
if(visit[y])
{
t=la[t];
continue ;
}
fa[y][0]=x;
dep[y]=dep[x]+1;
val[y][0]=len[t];
visit[y]=true;
dfs(y);
t=la[t];
}
}
//...................................................................
/*void go_up(int &v,int p)
{
for(int i=0;i<=s;i++) if(p&(1<<i)) v=fa[v][i];
}*/
int lca(int u,int v)
{
if(dep[u]>dep[v]) swap(u,v);
//go_up(v,dep[v]-dep[u]);
int p=dep[v]-dep[u],ans=1e9;
for(int i=0;i<=s;i++) if((p>>i)&1) ans=min(ans,val[v][i]),v=fa[v][i];
if(v==u) return ans;
for(int i=s;i>=0;i--) if(fa[v][i]!=fa[u][i]) ans=min(ans,min(val[v][i],val[u][i])),v=fa[v][i],u=fa[u][i];
return min(ans,min(val[v][0],val[u][0]));
}
/*int getmin(int v,int u)//u 在 v上方
{
int p=dep[v]-dep[u],ans=inf;
for(int i=0;i<=s;i++)
if(p&(1<<i))
{
ans=min(ans,val[v][i]);
v=fa[v][i];
}
return ans;
}*/
//...................................................................
int main()
{
//freopen("a.txt","r",stdin);
int n,m;in_(n),in_(m);//scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) belong[i]=i;
for(int i=1;i<=m;i++) in_(w[i].a),in_(w[i].b),in_(w[i].val);//scanf("%d%d%d",&w[i].a,&w[i].b,&w[i].val);
//...................................................................
sort(w+1,w+1+m,way);
int x,y;
for(int i=1;i<=m;i++)
{
x=getbelong(w[i].a),y=getbelong(w[i].b);
if(x!=y)
{
belong[x]=y;
add(w[i].a,w[i].b,w[i].val),add(w[i].b,w[i].a,w[i].val);
}
}
//...................................................................
for(int i=1;i<=n;i++)
if(!use[getbelong(i)])
{
visit[i]=true;
dfs(i);
use[getbelong(i)]=true;
}
//...................................................................
int q;in_(q);//scanf("%d",&q);
for(int i=1,a,b;i<=q;i++)
{
in_(x),in_(y);//scanf("%d%d",&x,&y);
if(getbelong(x)!=getbelong(y)) puts("-1");
else
{
out_(lca(x,y));
//a=getmin(x,c),b=getmin(y,c);
//out_(min(a,b));//printf("%d\n",min(a,b));
}
}
}