倍增LCA NOIP2013 货车运输

货车运输

题目描述

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。

NOIP2013,模板题???

不!

这可能是个森林!!!然而善心大发的CCF可能没有专门造数据卡直接用最大生成树写的人……

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring> 
 4 #include<algorithm>
 5 using namespace std;
 6 struct data{
 7     int next,to,dis;
 8 }edge[20010];
 9 struct dt{
10     int x,y,ds;
11 }eg[50010];
12 int n,m,q,cnt,tot;
13 int head[10010],deep[10010],w[10010][32],f[10010],fa[10010][32];
14 bool cmp(const dt&aa,const dt&bb){
15     return aa.ds>bb.ds;
16 }
17 int find(int x){
18     if(x!=f[x]) return f[x]=find(f[x]);
19     return x;
20 }
21 void add(int start,int end,int d){
22     edge[++cnt].next=head[start];
23     edge[cnt].to=end;
24     edge[cnt].dis=d;
25     head[start]=cnt;
26 }
27 void work(){
28     for(int j=0;(1<<j)<=n;j++)
29         for(int i=1;i<=n;i++)
30             if(fa[i][j-1]!=-1){
31                 fa[i][j]=fa[fa[i][j-1]][j-1];
32                 w[i][j]=min(w[i][j-1],w[fa[i][j-1]][j-1]);
33             }
34 }
35 void dfs(int u){
36     for(int i=head[u];i;i=edge[i].next)
37         if(!deep[edge[i].to]){
38             deep[edge[i].to]=deep[u]+1;
39             w[edge[i].to][0]=edge[i].dis;
40             fa[edge[i].to][0]=u;
41             dfs(edge[i].to);
42         }
43 }
44 int lca(int ss,int ee){
45     if(deep[ss]<deep[ee]) swap(ss,ee);
46     int i=0,rt=0x3f3f3f3f;
47     for(i=0;(1<<i)<=deep[ss];i++);
48     i--;
49     for(int j=i;j>=0;j--)
50         if(deep[ss]-(1<<j)>=deep[ee]){
51             rt=min(rt,w[ss][j]);
52             ss=fa[ss][j];
53         }
54     if(ss==ee) return rt;
55     for(int j=i;j>=0;j--)
56         if(fa[ss][j]!=-1&&fa[ss][j]!=fa[ee][j]){
57             rt=min(rt,min(w[ss][j],w[ee][j]));
58             ss=fa[ss][j];
59             ee=fa[ee][j];
60         }
61     return min(rt,min(w[ee][0],w[ss][0]));
62 }
63 int main(){
64     scanf("%d%d",&n,&m);
65     for(int i=1;i<=m;i++) scanf("%d%d%d",&eg[i].x,&eg[i].y,&eg[i].ds);
66     sort(eg+1,eg+m+1,cmp);
67     for(int i=1;i<=n;i++) f[i]=i;
68     int f1,f2;
69     for(int i=1;i<=m;i++){
70         f1=find(eg[i].x);
71         f2=find(eg[i].y);
72         if(f1!=f2){
73             f[f1]=f2;
74             add(eg[i].x,eg[i].y,eg[i].ds);
75             add(eg[i].y,eg[i].x,eg[i].ds);
76             tot++;
77         }
78         if(tot==n-1) break;
79     }
80     memset(fa,-1,sizeof(fa));
81     for(int i=1;i<=n;i++) 
82         if(!deep[i]){
83             deep[i]=1;
84             dfs(i);
85         }
86     work();
87     scanf("%d",&q);
88     int s,e;
89     for(int i=1;i<=q;i++){
90         scanf("%d%d",&s,&e);
91         if(find(s)!=find(e)){
92             printf("-1
");
93             continue;
94         }
95         printf("%d
",lca(s,e));
96     }
97     return 0;
98 }
原文地址:https://www.cnblogs.com/zwube/p/6906472.html