NOIP2013货车运输
NOIP2013貨車運輸
題目描述
A 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現(xiàn)在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。
輸入
第一行有兩個用一個空格隔開的整數(shù)n,m,表示A國有n座城市和m條道路。接下來m行每行3個整數(shù)x、y、z,每兩個整數(shù)之間用一個空格隔開,表示從x號城市到y(tǒng)號城市有一條限重為z的道路。注意:x不等于y,兩座城市之間可能有多條道路。接下來一行有一個整數(shù)q,表示有q輛貨車需要運貨。接下來q行,每行兩個整數(shù)x、y,之間用一個空格隔開,表示一輛貨車需要從x城市運輸貨物到y(tǒng)城市,注意:x不等于y。
數(shù)據(jù)范圍:n最大10000,m最大50000,q為30000,z為100000.
輸出
共有q行,每行一個整數(shù),表示對于每一輛貨車,它的最大載重是多少。如果貨車不能到達(dá)目的地,輸出-1。
樣例輸入
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
樣例輸出
3
-1
3
做法
兩點之間盡可能大的最小承重路徑一定在最大生成樹上,于是問題轉(zhuǎn)化為查詢最大生成樹上,兩點之間的最小邊的查詢,可以倍增,也可以樹剖。注意還有可能不能互相到達(dá)。
#include <bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;++i) typedef long long ll; const int N = 10010; const int M = 50100; const int inf = 0x3f3f3f3f; inline int read() {char c=getchar(); int x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } using namespace std; struct edge{int u,v,nxt,w;}E[M<<1],E0[M<<1]; int h[N],cc; void add(int u,int v,int z) {E[cc].v=v;E[cc].w=z;E[cc].nxt=h[u];h[u]=cc;++cc; } bool cmp(edge a,edge b) {return a.w > b.w;} int n,m; int f[N][22],mn[N][22],fa[N]; int find(int x) {if(x==fa[x])return x;return fa[x]=find(fa[x]); } void merge(int x,int y) {x=find(x), y =find(y);if(x!=y) fa[x]=y; } void krus() {sort(E0+1,E0+1+m,cmp);rep(i,1,m) {int tx = find(E0[i].u), ty = find(E0[i].v);if(tx!=ty) {merge(tx,ty);add(E0[i].u,E0[i].v,E0[i].w);add(E0[i].v,E0[i].u,E0[i].w);}} } bool vis[N]; int dep[N]; void dfs(int u,int pre) {vis[u] = 1;f[u][0] = pre;for(int i=h[u];~i;i=E[i].nxt) {int v = E[i].v;if(!vis[v]&&v!=pre) {dep[v]=dep[u]+1;mn[v][0] = E[i].w;dfs(v,u);for(int j=1;j<=20;++j) f[v][j] = f[f[v][j-1]][j-1];for(int j=1;j<=20;++j) mn[v][j] = min(mn[v][j-1],mn[f[v][j-1]][j-1]);}} } void init() {memset(mn,inf,sizeof(mn));krus();rep(i,1,n)if(!vis[i])dfs(i,0); // rep(i,1,n) { // printf("%d :\n",i); // printf("dep[%d] = %d\n",i,dep[i]); // rep(j,0,3) printf("fa[%d][%d] = %d\n",i,j,f[i][j]); // rep(j,0,3) printf("mn[%d][%d] = %d\n",i,j,mn[i][j]); // } } int lca(int x,int y) {if(dep[x] > dep[y]) swap(x,y);int tx=x,ty=y;for(int d=dep[y]-dep[x],i=0;d;d>>=1,++i) if(d&1) ty = f[ty][i];if(tx == ty) return tx;for(int i=20;i>=0;--i) {if(f[tx][i]==f[ty][i]) continue;tx = f[tx][i], ty = f[ty][i];}return f[tx][0]; } int ask_mn(int x,int p) {int ans = inf, tx=x;for(int d=dep[x]-dep[p],i=0;d;d>>=1,++i) if(d&1) {ans = min(ans,mn[tx][i]);tx = f[tx][i];}return ans; } int ask(int x,int y) {if(find(x)!=find(y)) return -1;int LCA = lca(x,y);return min(ask_mn(x,LCA),ask_mn(y,LCA)); } int main() {n = read(), m =read();rep(i,1,n) h[i]=-1,fa[i]=i;rep(i,1,m) E0[i].u=read(),E0[i].v=read(),E0[i].w=read();init();int q = read();while(q--) {int x=read(), y =read();printf("%d\n",ask(x,y));}return 0; } //9 8 //1 2 4 //1 5 3 //2 3 3 //2 4 2 //3 9 2 //3 8 7 //5 7 6 //5 6 7轉(zhuǎn)載于:https://www.cnblogs.com/RRRR-wys/p/9384040.html
總結(jié)
以上是生活随笔為你收集整理的NOIP2013货车运输的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 代码显示科乐美正酝酿第 2 卷大师合集,
- 下一篇: 概率期望学习笔记