货车运输

题目描述

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

输入输出格式

输入格式:

 

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

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

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

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

 

输出格式:

 

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

 

就是每条路径上取一个最小值,有多条路径时取一个最大值,但对每组询问都跑一边SPFA肯定是不对的。

 

然后看了标签,就是求一个最大生成树,然后用倍增维护最小值......

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=1e4+7;
 7 const int maxm=5e4+7;
 8 int n,m,num,q,ans,tot;
 9 int head[maxn],fa[maxn],dep[maxn],f[maxn][27],imin[maxn][27];
10 struct E{
11   int from,to,dis;
12 }e[maxm];
13 struct Edge{
14   int next,to,dis;
15 }edge[maxm];
16 void add(int from,int to,int dis){
17   edge[++num].next=head[from];
18   edge[num].to=to;
19   edge[num].dis=dis;
20   head[from]=num; 
21 }
22 bool cmp(E a,E b){return a.dis>b.dis;}
23 int find(int x){
24   if(fa[x]==x) return x;
25   return fa[x]=find(fa[x]);
26 }
27 void merge(int x,int y){
28  int fx=find(x);int fy=find(y);
29  if(fx!=fy) fa[fx]=fy;
30 }
31 void kruskal(){
32   int cnt=0;
33   for(int i=1;i<=n;i++) fa[i]=i;
34   for(int i=1;i<=tot;i++){
35     int u=e[i].from;int v=e[i].to;
36     int fu=find(u);int fv=find(v);
37     if(fu!=fv){
38       merge(fu,fv);cnt++;
39       add(u,v,e[i].dis);add(v,u,e[i].dis);
40     }
41     if(cnt==n-1) return;
42   }
43 }
44 void prepare(int x,int pre){
45   dep[x]=dep[pre]+1;
46   for(int i=1;i<=19;i++){
47     f[x][i]=f[f[x][i-1]][i-1];
48     imin[x][i]=min(imin[x][i-1],imin[f[x][i-1]][i-1]);
49   }
50   for(int i=head[x];i;i=edge[i].next){
51     int v=edge[i].to;
52     if(v==pre) continue;
53     f[v][0]=x;imin[v][0]=edge[i].dis;
54     prepare(v,x);
55   }
56 }
57 void process(int x,int y){
58   int ans1=0x7f7f7f7f;int ans2=0x7f7f7f7f;
59   if(dep[x]<dep[y]) swap(x,y);
60   for(int i=20;i>=0;i--){
61     if(dep[f[x][i]]>=dep[y]){ans=min(ans1,imin[x][i]);x=f[x][i];}
62   }
63   if(x==y){ans=min(ans1,ans2);return;}
64   for(int i=20;i>=0;i--){
65     if(f[x][i]!=f[y][i]){
66       ans1=min(ans1,imin[x][i]);ans2=min(ans2,imin[y][i]);
67       x=f[x][i];y=f[y][i];
68     }
69   }
70   ans1=min(ans1,imin[x][0]);ans2=min(ans2,imin[y][0]);
71   ans=min(ans1,ans2);return;
72 }
73 int main(){
74   cin>>n>>m;
75   for(int i=1;i<=n;i++){
76     int x,y,w;cin>>x>>y>>w;
77     e[++tot].from=x;e[tot].to=y;e[tot].dis=w;
78   }
79   sort(e+1,e+tot+1,cmp);
80   kruskal();
81   memset(imin,0x7f7f7f7f,sizeof(imin));
82   prepare(1,0);
83   cin>>q;
84   while(q--){
85     int x,y;cin>>x>>y;
86     ans=0x7f7f7f7f;process(x,y);
87     if(ans==0x7f7f7f7f) cout<<"-1"<<endl;
88     else cout<<ans<<endl;
89   }
90   return 0;
91 }

 上面没有考虑多棵树

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 typedef long long ll;
  7 const int maxn=1e4+7;
  8 const int maxm=5e4+7;
  9 ll n,m,num,q,ans,tot;
 10 ll head[maxn],fa[maxn],dep[maxn],f[maxn][27],imin[maxn][27];
 11 struct E{
 12   int from,to,dis;
 13 }e[maxm];
 14 struct Edge{
 15   int next,to,dis;
 16 }edge[maxm];
 17 void add(int from,int to,int dis){
 18   edge[++num].next=head[from];
 19   edge[num].to=to;
 20   edge[num].dis=dis;
 21   head[from]=num; 
 22 }
 23 bool cmp(E a,E b){return a.dis>b.dis;}
 24 int find(int x){
 25   if(fa[x]==x) return x;
 26   return fa[x]=find(fa[x]);
 27 }
 28 void merge(int x,int y){
 29  int fx=find(x);int fy=find(y);
 30  if(fx!=fy) fa[fx]=fy;
 31 }
 32 void kruskal(){
 33   int cnt=0;
 34   for(int i=1;i<=n;i++) fa[i]=i;
 35   for(int i=1;i<=tot;i++){
 36     int u=e[i].from;int v=e[i].to;
 37     int fu=find(u);int fv=find(v);
 38     if(fu!=fv){
 39       merge(fu,fv);cnt++;
 40       add(u,v,e[i].dis);add(v,u,e[i].dis);
 41     }
 42     if(cnt==n-1) return;
 43   }
 44 }
 45 void prepare(int x,int pre){
 46   dep[x]=dep[pre]+1;
 47   for(int i=1;i<=19;i++){
 48       if(f[x][i-1]==0) break;
 49     f[x][i]=f[f[x][i-1]][i-1];
 50     imin[x][i]=min(imin[x][i-1],imin[f[x][i-1]][i-1]);
 51   }
 52   for(int i=head[x];i;i=edge[i].next){
 53     int v=edge[i].to;
 54     if(v==pre) continue;
 55     f[v][0]=x;imin[v][0]=edge[i].dis;
 56     prepare(v,x);
 57   }
 58 }
 59 bool process(int x,int y){
 60   ll ans1=0x7f7f7f7f;ll ans2=0x7f7f7f7f;
 61   if(dep[x]<dep[y]) swap(x,y);
 62   for(int i=20;i>=0;i--){
 63     if(dep[f[x][i]]>=dep[y]){ans1=min(ans1,imin[x][i]);x=f[x][i];}
 64   }
 65   if(x==y){ans=min(ans1,ans2);return true;}
 66   for(int i=20;i>=0;i--){
 67     if(f[x][i]!=f[y][i]){
 68       ans1=min(ans1,imin[x][i]);ans2=min(ans2,imin[y][i]);
 69       x=f[x][i];y=f[y][i];
 70     }
 71   }
 72   if(f[x][0]!=f[y][0]) return false;//因为是取最小值,所以INF会被忽略 
 73   else{
 74     ans1=min(ans1,imin[x][0]);ans2=min(ans2,imin[y][0]);
 75     ans=min(ans1,ans2);return true;
 76   }
 77 }
 78 int main(){
 79   cin>>n>>m;
 80   for(int i=1;i<=m;i++){
 81     int x,y,w;cin>>x>>y>>w;
 82     e[++tot].from=x;e[tot].to=y;e[tot].dis=w;
 83   }
 84   sort(e+1,e+tot+1,cmp);
 85   kruskal();
 86   memset(imin,0x7f7f7f7f,sizeof(imin));
 87   prepare(1,0);f[1][0]=1;
 88   for(int i=1;i<=n;i++){
 89     if(dep[i]==0) {prepare(i,0);f[i][0]=i;}
 90   }
 91   cin>>q;
 92   for(int i=1;i<=q;i++){
 93     int x,y;cin>>x>>y;
 94     ans=0x7f7f7f7f;
 95     if(!process(x,y)) cout<<"-1"<<endl;
 96     else if(ans==0x7f7f7f7f) cout<<"-1"<<endl;
 97     else cout<<ans<<endl;
 98   }
 99   return 0;
100 }

 

posted @ 2018-09-10 21:57  lcan  阅读(155)  评论(0编辑  收藏  举报