P1967 货车运输
数据范围
题目描述
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入输出格式
输入格式:
输入文件名为 truck.in。
输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道
路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
输出格式:
输出文件名为 truck.out。
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货
车不能到达目的地,输出-1。
输入输出样例
输入样例#1:
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
输出样例#1:
3
-1
3
说明
对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000; 对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000; 对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。
注意:
1.注意维护limit数组和f数组的时候的顺序
2.可以加入另一个并查集数组判断-1的情况,优化。
3.求最大生成树注意有重边的情况,所以先进行一遍从大到小的排序,先加入的边一定是最优的。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100006
#define inf 2147483647
using namespace std;
int e_num,n,m;
int head[N*2];
int father[N],mother[N];
int deep[N],vis[N];
struct node1
{
int x,y,v;
}love[N];
struct node2
{
int to,dis,next;
}e[N*2];
struct node3
{
int c,fa;
}f[N*2][20];
int get()
{
int x=0,p=1;char c;
c=getchar();
while (c<'0'||c>'9') {if (c=='-') p=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*p;
}
void add(int from,int to,int dis)
{
++e_num;
e[e_num].to=to;
e[e_num].dis=dis;
e[e_num].next=head[from];
head[from]=e_num;
}
bool cmp(node1 a,node1 b)
{
return a.v>b.v;
}
int find_father(int x)
{
if (father[x]!=x) father[x]=find_father(father[x]);
return father[x];
}
void mix_father(int x,int y)
{
int xx,yy;
xx=find_father(x);
yy=find_father(y);
father[yy]=xx;
}
int find_mother(int x)
{
if (mother[x]!=x) mother[x]=find_mother(mother[x]);
return mother[x];
}
void mix_mother(int x,int y)
{
int xx,yy;
xx=find_mother(x);
yy=find_mother(y);
mother[yy]=xx;
}
void rmq(int t)
{
int i;
for (i=1;i<=20;i++)
{
if (deep[t]<(1<<i))
break;
f[t][i].c=min(f[f[t][i-1].fa][i-1].c,f[t][i-1].c);
f[t][i].fa=f[f[t][i-1].fa][i-1].fa;
}
vis[t]=true;
for (i=head[t];i;i=e[i].next)
if (!vis[e[i].to])
{
deep[e[i].to]=deep[t]+1;
f[e[i].to][0].fa=t;
f[e[i].to][0].c=e[i].dis;
rmq(e[i].to);
}
}
void kruskal()
{
int i,k=0;
for (i=1;i<=m;i++)
{
if (find_father(love[i].x)==find_father(love[i].y))
continue;
mix_father(love[i].x,love[i].y);
k++;
add(love[i].x,love[i].y,love[i].v);
add(love[i].y,love[i].x,love[i].v);
if (k==n-1) break;
}
}
int lca(int x,int y)
{
int i,ans=inf;
if (deep[x]<deep[y])
{
swap(x,y);
}
for (i=20;i>=0;i--)
{
if (deep[x]-deep[y]>=(1<<i))
{
ans=min(f[x][i].c,ans);
x=f[x][i].fa;
}
}
if (x==y) return ans;
int u=0;
while (deep[x]>=(1<<u)) u++;
for (i=u;i>=0;i--)
if (f[x][i].fa!=f[y][i].fa)
{
ans=min(f[x][i].c,ans);
x=f[x][i].fa;
ans=min(f[y][i].c,ans);
y=f[y][i].fa;
}
return min(ans,min(f[x][0].c,f[y][0].c));
}
int main()
{
int x,y,i;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) mother[i]=i;
for (i=1;i<=m;i++)
{
love[i].x=get();love[i].y=get();love[i].v=get();
mix_mother(love[i].x,love[i].y);
}
sort(love+1,love+m+1,cmp);
for (i=1;i<=n;i++) father[i]=i;
kruskal();
rmq(1);
int q=get();
for (i=1;i<=q;i++)
{
x=get();y=get();
if (find_mother(x)!=find_mother(y)) {printf("-1\n");continue;}
printf("%d\n",lca(x,y));
}
}