洛谷P1967 [NOIP2013提高组Day1T2]货车运输
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。
【题解】
最大生成树+树上倍增,证明可用反证法或者显然法(唔)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #define min(a, b) ((a) < (b) ? (a) : (b)) 7 8 inline void read(int &x) 9 { 10 x = 0;char ch = getchar(), c = ch; 11 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 12 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 13 if(c == '-') x = -x; 14 } 15 16 inline void swap(int &a, int &b) 17 { 18 int tmp = a;a = b;b = tmp; 19 } 20 21 const int MAXN = 10000 + 10; 22 const int MAXM = 50000 + 10; 23 const int INF = 0x3f3f3f3f; 24 25 int n,m,u[MAXM],v[MAXM],w[MAXM],cnt[MAXM],q,s,t,fa[MAXN],b[MAXM]; 26 27 bool cmp(int a, int b) 28 { 29 return w[a] > w[b]; 30 } 31 32 struct Edge 33 { 34 int u,v,w,next; 35 Edge(int _u, int _v, int _w, int _next){u = _u, v = _v, w = _w, next = _next;} 36 Edge(){} 37 }edge[MAXN << 1]; 38 int head[MAXN], cntt; 39 inline void insert(int a, int b, int c) 40 { 41 edge[++cntt] = Edge(a,b,c,head[a]); 42 head[a] = cntt; 43 } 44 45 int deep[MAXN], p[20][MAXN], mi[20][MAXN]; 46 47 void dfs(int u) 48 { 49 b[u] = 1; 50 for(register int pos = head[u];pos;pos = edge[pos].next) 51 { 52 int v = edge[pos].v; 53 if(b[v])continue; 54 deep[v] = deep[u] + 1; 55 p[0][v] = u; 56 mi[0][v] = edge[pos].w; 57 dfs(v); 58 } 59 } 60 61 void yuchuli() 62 { 63 int M = 0; 64 while((1 << M) <= n) ++ M; 65 -- M; 66 for(register int i = 1;i <= M;++ i) 67 for(register int j = 1;j <= n;++ j) 68 p[i][j] = p[i - 1][p[i - 1][j]]; 69 for(register int i = 1;i <= M;++ i) 70 for(register int j = 1;j <= n;++ j) 71 mi[i][j] = min(mi[i - 1][p[i - 1][j]], mi[i - 1][j]); 72 } 73 74 int LCA(int va, int vb) 75 { 76 if(deep[va] < deep[vb]) swap(va, vb); 77 int M = 0; 78 while((1 << M) <= n)++ M; 79 -- M; 80 for(register int i = M;i >= 0;-- i) 81 if(deep[vb] + (1 << i) <= deep[va]) 82 va = p[i][va]; 83 if(va == vb)return va; 84 M = 0; 85 while((1 << M) <= deep[va]) ++ M; 86 -- M; 87 for(register int i = M;i >= 0;-- i) 88 if(p[i][va] != p[i][vb]) 89 { 90 va = p[i][va]; 91 vb = p[i][vb]; 92 } 93 return p[0][va]; 94 } 95 96 int find(int x) 97 { 98 return x == fa[x] ? x : fa[x] = find(fa[x]); 99 } 100 101 int main() 102 { 103 read(n), read(m); 104 for(register int i = 1;i <= m;++i) 105 read(u[i]), read(v[i]), read(w[i]), cnt[i] = i; 106 for(register int i = 1;i <= n;++ i) 107 fa[i] = i; 108 std::sort(cnt + 1, cnt + 1 + m, cmp); 109 for(register int i = 1;i <= m;++i) 110 { 111 int f1 = find(u[cnt[i]]), f2 = find(v[cnt[i]]); 112 if(f1 != f2) 113 { 114 fa[f1] = f2; 115 insert(u[cnt[i]], v[cnt[i]], w[cnt[i]]); 116 insert(v[cnt[i]], u[cnt[i]], w[cnt[i]]); 117 } 118 } 119 for(register int i = 1;i <= n;++ i) 120 { 121 if(!b[i]) 122 { 123 deep[i] = 1; 124 dfs(i); 125 } 126 } 127 yuchuli(); 128 read(q); 129 int s,t; 130 int M = 0; 131 while((1 << M) <= n) ++ M; 132 -- M; 133 for(register int i = 1;i <= q;++ i) 134 { 135 read(s), read(t); 136 int f1 = find(s), f2 = find(t); 137 if(f1 != f2) 138 { 139 printf("-1\n"); 140 continue; 141 } 142 int lca = LCA(s, t); 143 int mi1 = INF, mi2 = INF; 144 for(register int j = M;j >= 0;-- j) 145 if(p[j][s] && deep[p[j][s]] >= deep[lca]) 146 { 147 mi1 = min(mi1, mi[j][s]); 148 s = p[j][s]; 149 } 150 for(register int j = M;j >= 0;-- j) 151 if(p[j][t] && deep[p[j][t]] >= deep[lca]) 152 { 153 mi2 = min(mi2, mi[j][t]); 154 t = p[j][t]; 155 } 156 printf("%d\n", min(mi1, mi2)); 157 } 158 return 0; 159 }