NOIP 2013 货车运输

Posted zhangenming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP 2013 货车运输相关的知识,希望对你有一定的参考价值。

货车运输

描述

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

格式

输入格式

第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。

接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。

接下来一行有一个整数 q,表示有 q 辆货车需要运货。

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

输出格式

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

样例1

样例输入1

??4 3 
1 2 4 
2 3 3 
3 1 1 
3
1 3 
1 4 
1 3

样例输出1

3
-1
3

限制

每个测试点1s。

提示

对于 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。

来源

NOIP 2013 提高组 Day 1

来自hzwer

这是一个求瓶颈路的问题首先对于30%的数据可以使用暴力,直接一个spfa算法,不断更新到每个结点的瓶颈路这是一个经典的问题,我们发现,最优解一定是在原图的最大生成森林上

因为不在最大生成森林上的路径一定是更劣的

那么如果我们只拿出最大生成森林做spfa的话,边的大小降为n,可以通过60%的数据

其实本题是模板题,询问森林中两个点的路径上的最小边权,连通性用并查集判一下

可以用树上倍增在logn的复杂度解决一棵树内的一次询问

预处理F(i,j)表示第i个点距离为2^j的祖先,这个可以深搜整棵树再递推一下,复杂度nlogn

G(i,j)表示第i个点到其距离为2^j的祖先上的最小权值,然后用倍增的思想俩个点往上跳一跳更新答案就行辣

技术分享图片
  1 #include <bits/stdc++.h>
  2 #define ll long long
  3 #define inf 100000000
  4 #define eps 1e-7
  5 using namespace std;
  6 inline int read(){
  7     int x=0;int f=1;char ch=getchar();
  8     while(!isdigit(ch)) {if(ch==-) f=-1;ch=getchar();}
  9     while(isdigit(ch)) {x=x*10+ch-0;ch=getchar();}
 10     return x*f;
 11 }
 12 const int MAXN=1e6+10;
 13 struct node{
 14     int v,y,next;
 15 }e[MAXN];
 16 struct edge{
 17     int x,y,v;
 18 }a[MAXN];
 19 int linkk[MAXN],len=0,n,m,fa[MAXN],f[MAXN][30],d[MAXN][30],vis[MAXN],ans,dep[MAXN];
 20 inline void insert(int xx,int yy,int vv){
 21     e[++len].y=yy;e[len].next=linkk[xx];e[len].v=vv;linkk[xx]=len;
 22 }
 23 inline bool mycmp(edge n,edge m){
 24     return n.v>m.v;
 25 }
 26 inline int find(int xx){
 27     return xx==fa[xx]?xx:fa[xx]=find(fa[xx]);
 28 }
 29 namespace zhangenming{
 30     inline void kruskal(){
 31         for(int i=1;i<=n;i++){
 32             fa[i]=i;
 33         }
 34         for(int i=1;i<=m;i++){
 35             int xx=a[i].x;int yy=a[i].y;
 36             int fx=find(xx);int fy=find(yy);
 37             if(fx!=fy){
 38                 fa[fx]=fy;insert(a[i].x,a[i].y,a[i].v),insert(a[i].y,a[i].x,a[i].v);
 39             }
 40         }
 41     }
 42     inline void dfs(int st,int father){
 43         f[st][0]=father;dep[st]=dep[father]+1;
 44         vis[st]=1;
 45         for(int i=linkk[st];i;i=e[i].next){
 46             if(!vis[e[i].y]){
 47                 d[e[i].y][0]=e[i].v;
 48                 dfs(e[i].y,st);
 49             }
 50         }
 51     }
 52     void init(){
 53         n=read();m=read();
 54         for(int i=1;i<=m;i++){
 55            a[i].x=read();a[i].y=read();a[i].v=read();        
 56         }
 57         sort(a+1,a+m+1,mycmp);
 58     }
 59     void getanser(){
 60         for(int i=1;i<=25;i++){
 61             for(int j=1;j<=n;j++){
 62                 if(f[j][i-1]){
 63                     d[j][i]=min(d[j][i-1],d[f[j][i-1]][i-1]);
 64                     f[j][i]=f[f[j][i-1]][i-1];
 65                 }
 66             }
 67         }
 68     }
 69     inline void LCA(int xx,int yy){
 70         if(xx==yy) return;
 71         if(dep[xx]<dep[yy]) swap(xx,yy);
 72         for(int i=25;i>=0;i--){
 73             if(dep[xx]-(1<<i)>=dep[yy]) ans=min(ans,d[xx][i]),xx=f[xx][i];
 74         }
 75         if(xx==yy) return;
 76         for(int i=25;i>=0;i--){
 77             if(f[xx][i]!=f[yy][i]&&f[xx][i]){
 78                 ans=min(ans,d[xx][i]);ans=min(ans,d[yy][i]);
 79                 xx=f[xx][i];yy=f[yy][i];
 80             }
 81         }
 82         ans=min(ans,d[xx][0]);ans=min(ans,d[yy][0]);
 83     }
 84     void solve(){
 85         kruskal();
 86         memset(d,10,sizeof(f));
 87         for(int i=1;i<=n;i++){
 88             if(!vis[i]) dfs(i,0);
 89         }
 90         getanser();    
 91         int T=read();
 92         while(T--){
 93             int xx=read();int yy=read();
 94             ans=inf;
 95             if(find(xx)!=find(yy)){
 96                 printf("-1\n");
 97             }
 98             else{
 99                 LCA(xx,yy);
100                 printf("%d\n",ans);
101             }
102         }
103     }
104 }
105 int main(){
106     using namespace zhangenming;
107     init();
108     solve();
109     return 0;
110 }
View Code

 



以上是关于NOIP 2013 货车运输的主要内容,如果未能解决你的问题,请参考以下文章

[NOIP2013]货车运输

NOIP 2013 货车运输

3287 货车运输 2013年NOIP全国联赛提高组 40 分

[NOIP2013]货车运输

NOIP2013货车运输

NOIP2013 货车运输