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));
}
}