【NOIP 2013】货车运输 倍增+kruskal
2017-08-05 16:17
309 查看
题目描述 Description
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入描述 Input Description
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
输出描述 Output Description
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
样例输入 Sample Input
样例输出 Sample Output
数据范围及提示 Data Size & Hint
题解:
这个题目首先我们先用kruskal,跑一遍最大生成树,然后我们在这个最大生成树上面跑倍增,并且维护两点的之间的最小值。
证明:
为什么在最大生成树上跑倍增就可以了呢?因为若我们跑的是最大生成树这样的话,这样树上任意两点之间的最短路一定大于或等于其他连接这两点的路径的值。
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入描述 Input Description
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
输出描述 Output Description
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-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
数据范围及提示 Data Size & Hint
对于 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。
题解:
这个题目首先我们先用kruskal,跑一遍最大生成树,然后我们在这个最大生成树上面跑倍增,并且维护两点的之间的最小值。
证明:
为什么在最大生成树上跑倍增就可以了呢?因为若我们跑的是最大生成树这样的话,这样树上任意两点之间的最短路一定大于或等于其他连接这两点的路径的值。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <string> using namespace std; const int MAXN = 10005,MAXX = 5000005,MAXD = 20; int head[MAXN],Fa[MAXN],deep[MAXN],Min[MAXN][23],anc[MAXN][23]; int T,N,M,e = 1,sum,dist; struct node{ int v,c,next; }edge[MAXX]; struct ABC{ friend bool operator < (const ABC &a,const ABC &b){ return a.c > b.c; } int u,v,c; }Tree[MAXX]; inline void addedge(int u,int v,int c){ edge[e] = {v,c,head[u]};head[u] = e++; edge[e] = {u,c,head[v]};head[v] = e++; } inline int read() { int x = 0;char ch = getchar(); while(ch < '0' || '9' < ch){ch = getchar();} while('0' <= ch && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x; } int Find_set(int x){ return Fa[x] == x ? x : Fa[x] = Find_set(Fa[x]);} inline void Union(int x,int y,int c){ int fx = Find_set(x); int fy = Find_set(y); Fa[fx] = fy; addedge(x,y,c); } void dfs(int u,int h){ deep[u] = h; for(int i = 1;i <= MAXD;i++){ anc[u][i] = anc[ anc[u][i-1] ][i-1]; Min[u][i] = min( Min[ anc[u][i-1] ][i-1] , Min[u][i-1] ); } for(int i = head[u];i;i = edge[i].next){ int v = edge[i].v,c = edge[i].c; if(!deep[v]){ anc[v][0] = u; Min[v][0] = c; dfs(v,h+1); } } } inline int swim(int &u,int v){ dist = 1100000; for(int i = MAXD;i >= 0;i--) if(deep[anc[u][i]] > deep[v]){ dist = min(dist,Min[u][i]); u = anc[u][i]; } if(deep[u] != deep[v]){ dist = min(dist,Min[u][0]); u = anc[u][0]; } return dist; } inline void query(int x,int y){ dist = 1100000; if(deep[x] < deep[y]) swap(x,y); dist = min(dist,swim(x,y)); if(x == y) return; for(int i = MAXD;i >= 0;i--) if(anc[x][i] != anc[y][i]){ dist = min(Min[x][i],dist); dist = min(Min[y][i],dist); x = anc[x][i]; y = anc[y][i]; } if(x != y) dist = min( dist , min( Min[x][0] , Min[y][0] ) ); } inline void init() { N = read();M = read(); for(int i = 1;i <= M;i++){ Tree[i].u = read(); Tree[i].v = read(); Tree[i].c = read(); } for(int i = 1;i <= N;i++) Fa[i] = i; sort(Tree+1,Tree+1+M); for(int i = 1;i <= M;i++) { if(Find_set(Tree[i].u) != Find_set(Tree[i].v)) Union(Tree[i].u,Tree[i].v,Tree[i].c); } dfs(1,1); int Q = read();int U,V; for(int i = 1;i <= Q;i++){ U = read();V = read(); if(Find_set(U) == Find_set(V)) query(U,V),printf("%d\n",dist); else printf("-1\n"); } } int main() { init(); return 0; }
相关文章推荐
- noip2013 货车运输 (求解生成树路径上的最短边:倍增求最近共祖先+最大生成树Kruskal)
- [NOIP2013][CODEVS3287]货车运输(kruskal+树上倍增)
- Luogu1967 [NOIP2013] 货车运输 解题报告【Kruskal】【LCA】【倍增】
- NOIP2013 D1 T3 货车运输 树上倍增lca+Kruskal
- CodeVS3287[NOIP2013] 货车运输【Kruskal+倍增求LCA】
- [noip2013]货车运输(kruskal + 树上倍增)
- [NOIP2013]货车运输 D1 T3 kruscal最大生成树+树上倍增lca+rmq
- NOIP2013 货车运输 [LCA] [RMQ] [最小生成树] [ST倍增]
- 倍增LCA NOIP2013 货车运输
- NOIP 2013 货车运输(树上倍增)
- NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】
- NOIP2013货车运输[lca&&kruskal]
- Noip2013 Day1 T3 货车运输(树上倍增)
- NOIP2013 货车运输 LCA倍增+最大生成树
- NOIP 2013 CODE[VS] 3287 货车运输 倍增LCA + 最大生成树
- NOIP2013 D1T3 货车运输 倍增LCA OR 并查集按秩合并
- 【NOIP2013提高组T3】货车运输-最大生成树+倍增LCA
- 【图论,树上路径倍增算法】NOIP2013货车运输
- NOIP2013 货车运输 解题报告(最大生成树+倍增lca)
- NOIP2013 D1T3 货车运输 倍增LCA OR 并查集按秩合并