NOIP201307貨車運輸

試題描述:A 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。如今有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的狀況下,最多能運多重的貨物。ios

輸入描述:git

第一行有兩個用一個空格隔開的整數 n,m,表示 A 國有 n 座城市和 m 條道路。
接下來 m 行每行 3 個整數 x、y、z,每兩個整數之間用一個空格隔開,表示從 x 號城市到 y 號城市有一條限重爲 z 的道路。注意:x 不等於 y,兩座城市之間可能有多條道路。
接下來一行有一個整數 q,表示有 q 輛貨車須要運貨。
接下來 q 行,每行兩個整數 x、y,之間用一個空格隔開,表示一輛貨車須要從 x 城市運輸貨物到 y 城市,注意:x 不等於 y。ide

輸出描述:函數

輸出共有 q 行,每行一個整數,表示對於每一輛貨車,它的最大載重是多少。若是貨車不能到達目的地,輸出-1。spa

樣例輸入:code

4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3blog

樣例輸出:get

3
-1
3it

數據範圍:io

對於 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。

題解:這道題其實就是讓咱們找一條路使得這條路上的最小值最大,由此咱們不難想到對任意的從u到v的一條咱們所需的路徑,必定是在這個圖的最大生成樹上,因此咱們能夠先構造最大生成樹。

對於任意一組(u,v)(從u到v)用並查集能夠判斷若是u、v的祖先不一樣,那就說明u、v之間沒有路

若是有路,咱們用lca(最近公共祖先)來進行判斷。假設u、v的lca是t,那麼最終咱們須要的答案就是min(u到t的最短路限重,v到t的最短路限重),這樣咱們這個題就直接ac了

AC代碼以下:

  1 #include<iostream>
  2 #include<cctype>
  3 #include<algorithm>
  4 #include<memory.h>
  5 using namespace std;
  6 const int MAXN=100000+10;
  7 int n,m;
  8 //-------------------------
  9 void read(int &x){
 10     x=0;int f=1;char ch=getchar();
 11     for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 12     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
 13     x*=f;
 14 }//讀入函數 
 15 //-------------------------
 16 struct edge{
 17     int u,v,w;
 18     edge(){u=0;v=0;w=0;}
 19 }to[50010];
 20 bool operator < (edge a,edge b){return a.w>b.w;}
 21 //-------------------------
 22 int fa[10010];
 23 int find(int x){
 24     if(x==fa[x])return x;
 25     return fa[x]=find(fa[x]);
 26 }//並查集 
 27 //-------------------------
 28 int v[MAXN],w[MAXN],first[MAXN],next[MAXN],e;
 29 void AddEdge(int a,int b,int c){
 30     v[++e]=b;
 31     w[e]=c;
 32     next[e]=first[a];
 33     first[a]=e;
 34 }//鄰接表 
 35 void MST(){//最大生成樹 
 36     int cnt=0;
 37     sort(to+1,to+m+1);
 38     for(int i=1;i<=n;i++)fa[i]=i;
 39     for(int i=1;i<=m;i++){
 40         int p=find(fa[to[i].v]),q=find(fa[to[i].u]);
 41         if(p!=q){
 42             fa[p]=q;
 43             AddEdge(to[i].v,to[i].u,to[i].w);
 44             AddEdge(to[i].u,to[i].v,to[i].w);
 45             cnt++;
 46         }
 47         if(cnt==n-1)break;
 48     }
 49 }
 50 //------------------------
 51 int parent[17][10010];
 52 int depth[10010];
 53 int dist[17][MAXN]; 
 54 bool vis[10010];
 55 void dfs(int x,int p,int d){
 56     vis[x]=1;
 57     parent[0][x]=p;
 58     depth[x]=d;
 59     for(int i=first[x];i;i=next[i]){
 60         if(vis[v[i]])continue;
 61         dist[0][v[i]]=w[i];
 62         dfs(v[i],x,d+1);
 63     }
 64 }
 65 
 66 void init(){//初始化 
 67     for(int i=1;i<=n;i++)if(!vis[i])dfs(i,-1,0);
 68     for(int k=0;k+1<=16;k++){
 69         for(int i=1;i<=n;i++){
 70             if(parent[k][i]<0)parent[k+1][i]=-1;
 71             else parent[k+1][i]=parent[k][parent[k][i]];
 72             dist[k+1][i]=min(dist[k][parent[k][i]],dist[k][i]);
 73         }
 74     }
 75 }
 76 
 77 int lca(int x,int y){//最近公共祖先 
 78     if(depth[y]>depth[x])swap(x,y);
 79     for(int k=0;k<=16;k++)
 80         if((depth[x]-depth[y])>>k&1)
 81             x=parent[k][x];
 82     if(x==y)return x;
 83     for(int k=16;k>=0;k--){
 84         if(parent[k][x]!=parent[k][y]){
 85             x=parent[k][x];
 86             y=parent[k][y];
 87         }
 88     }
 89     return parent[0][x];
 90 }
 91 //------------------------------
 92 int work(int x,int y){
 93     int u=lca(x,y);
 94     int t1=depth[x]-depth[u];
 95     int t2=depth[y]-depth[u];
 96     int minn1=-1u>>1,minn2=-1u>>1;
 97     for(int i=0;i<=16;i++){
 98         if((t1&(1<<i))){
 99             minn1=min(minn1,dist[i][x]);
100             x=parent[i][x];
101         }
102         if(t2&(1<<i)){
103             minn2=min(minn2,dist[i][y]);
104             y=parent[i][y];
105         }
106     }
107     return min(minn1,minn2);
108 }
109 //-------------------------------
110 int main(){
111     memset(dist,127/3,sizeof(dist));
112     read(n);read(m);
113     for(int i=1;i<=m;i++){
114         read(to[i].u);
115         read(to[i].v);
116         read(to[i].w);
117     }
118     MST();
119     init();
120     int q;
121     read(q);
122     while(q--){
123         int x,y;
124         read(x);read(y);
125         if(find(x)!=find(y)){
126             printf("-1\n");
127             continue;
128         }
129         printf("%d\n",work(x,y));
130     }
131 }
View Code
相關文章
相關標籤/搜索