[noip2013]货车运输
Description
A国有n座城市,编号从1到n,城市之间有m条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有q辆货
车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
Input
第一行有两个用一个空格隔开的整数n,m,表示A国有n座城市和m条道路。
接下来m行每行3个整数x、y、z,每两个整数之间用一个空格隔开,表示从x号城市到y号城市有一条限重为z的道路。
注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数q,表示有q辆货车需要运货。
接下来q行,每行两个整数x、y,之间用一个空格隔开,表示一辆货车需要从x城市
运输货物到y城市,注意:x不等于y 。
0< N < 10,000
0< M < 50,000
0< Q < 30,000
0 < = z < = 100,000
接下来m行每行3个整数x、y、z,每两个整数之间用一个空格隔开,表示从x号城市到y号城市有一条限重为z的道路。
注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数q,表示有q辆货车需要运货。
接下来q行,每行两个整数x、y,之间用一个空格隔开,表示一辆货车需要从x城市
运输货物到y城市,注意:x不等于y 。
0< N < 10,000
0< M < 50,000
0< Q < 30,000
0 < = z < = 100,000
Output
输出共有q行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。
如果货车不能到达目的地,输出-1 。
如果货车不能到达目的地,输出-1 。
Sample Input
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
Sample Output
3
-1
3
首先,先建一个最大生成树,目的是为了将不必要的路径去掉,我们知道要得到最大的载重,肯定是要在每条路上载重肯定要尽量大,数据太大,采用kruskal来求。
建好图之后跑lca,得到最近公共祖先之后,再去求起点到最近公共祖先最小的承重和最近公共祖先到终点的最小载重,取其中较小值就是答案。
为什么取较小的,明明求的是最大载重。
举个例子,你在这条路上能载4kg的物品,但是下一段路只能载3kg,请问最大载重是4吗,如果是,下一段路怎么走?
所以,还是乖乖看代码吧
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 using namespace std; 6 int son[20001],nex[20001],pre[10001],fa[10001],f[10001][20],len[20001],k[10001],n,m,a,b,c,root,deep[10001],tot,ans,dis[10001][20]; 7 bool used[10001]; 8 struct oo 9 { 10 int a,b,c; 11 }v[50001]; 12 char ch; bool ok; 13 void read(int &x){ 14 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 15 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 16 if (ok) x=-x; 17 } 18 inline int find(int x) 19 { 20 if(k[x]==x)return x; 21 else k[x]=find(k[x]); 22 } 23 bool cmp(oo l,oo p) 24 { 25 return l.c>p.c; 26 } 27 inline void add(int x,int y,int z) 28 { 29 tot++; 30 son[tot]=y; 31 nex[tot]=pre[x]; 32 pre[x]=tot; 33 len[tot]=z; 34 } 35 inline void dfs(int now) 36 { 37 used[now]=1; 38 for(int i=1;i<=19;i++) 39 { 40 if(deep[now]<(1<<i))break; 41 f[now][i]=f[f[now][i-1]][i-1]; 42 dis[now][i]=min(dis[now][i-1],dis[f[now][i-1]][i-1]); 43 } 44 for(int i=pre[now];i;i=nex[i]) 45 { 46 int k=son[i]; 47 if(used[k])continue; 48 dis[k][0]=len[i]; 49 deep[k]=deep[now]+1; 50 f[k][0]=now; 51 dfs(k); 52 } 53 } 54 int put(int x,int y) 55 { 56 ans=923456789; 57 int t; 58 t=deep[x]-deep[y]; 59 for(int i=0;i<=19;i++) 60 { 61 if((1<<i)&t) 62 { 63 ans=min(ans,dis[x][i]); 64 x=f[x][i]; 65 } 66 } 67 return ans; 68 } 69 inline int lca(int x,int y) 70 { 71 if(deep[x]>deep[y])swap(x,y); 72 int poor=deep[y]-deep[x]; 73 for(int i=0;i<=19;i++) 74 if((1<<i)&poor) 75 y=f[y][i]; 76 for(int i=19;i>=0;i--) 77 if(f[x][i]!=f[y][i]) 78 x=f[x][i],y=f[y][i]; 79 if(x==y)return x; 80 return f[x][0]; 81 } 82 int main() 83 { 84 memset(dis,-1,sizeof(dis)); 85 read(n);read(m); 86 for(int i=1;i<=n;i++) 87 k[i]=i; 88 for(int i=1;i<=m;i++) 89 read(v[i].a),read(v[i].b),read(v[i].c); 90 sort(v+1,v+m+1,cmp); 91 int sum,num=0; 92 for(int i=1;i<=m;i++) 93 { 94 int w=v[i].a,e=v[i].b; 95 int x=find(v[i].a),y=find(v[i].b); 96 if(x!=y) 97 { 98 k[x]=y; 99 add(w,e,v[i].c); 100 add(e,w,v[i].c); 101 num++; 102 if(num==n-1)break; 103 } 104 } 105 for(int i=1;i<=n;i++)if(!used[i])dfs(i); 106 read(sum); 107 int begin,end; 108 for(int i=1;i<=sum;i++) 109 { 110 read(begin);read(end); 111 if(find(begin)!=find(end))printf("-1\n"); 112 else 113 { 114 int p=lca(begin,end); 115 printf("%d\n",min(put(begin,p),put(end,p))); 116 } 117 } 118 }