[luogu 1967]货车运输

货车运输

题目描述

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

输入输出格式

输入格式:

 

输入文件名为 truck.in。

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

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

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

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

 

输出格式:

 

输出文件名为 truck.out。

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货

车不能到达目的地,输出-1。

 

输入输出样例

输入样例#1:
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
输出样例#1:
3
-1
3

说明

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

题解:

求最大生成树,然后在最大生成树上跑LCA。

因为是最大生成树,所以这样得到的路径最小值必定是题目所要求的答案。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 using namespace std;
  8 int n,m,l,ans[30001],lim;
  9 int father[10001];
 10 struct node{int from,to,dis;}map[50001];
 11 int find(int x){if(father[x]==x)return x;else return father[x]=find(father[x]);}
 12 bool cmp(const node a,const node b){return a.dis>b.dis;}
 13 struct question{int s,t,id;}que[60001];
 14 int head[10001],size=1;
 15 struct Node{int next,to,dis;}edge[100005];
 16 void putin(int from,int to,int dis){size++;edge[size].dis=dis;edge[size].to=to;edge[size].next=head[from];head[from]=size;}
 17 int fa[10001][15],mmin[10001][15],vis[10001],dep[10001];
 18 void dfs(int r,int depth)
 19 {
 20     vis[r]=1;
 21     dep[r]=depth;
 22     for(int i=head[r];i!=-1;i=edge[i].next)
 23     {
 24         int y=edge[i].to;
 25         if(!vis[y])
 26         {
 27             fa[y][0]=r;
 28             mmin[y][0]=edge[i].dis;
 29             dfs(y,depth+1);
 30         }
 31     }
 32 }
 33 void RMQ()
 34 {
 35     for(int i=1;i<=lim;i++)
 36         for(int j=1;j<=n;j++)
 37         {
 38             fa[j][i]=fa[fa[j][i-1]][i-1];
 39             mmin[j][i]=min(mmin[j][i-1],mmin[fa[j][i-1]][i-1]);
 40         }
 41 }
 42 int LCA(int x,int y)
 43 {
 44     int i,j,ans=2000000000;
 45     if(dep[x]<dep[y])swap(x,y);
 46     for(i=lim;i>=0;i--)
 47         if(dep[x]-(1<<i)>=dep[y])
 48         {
 49             ans=min(ans,mmin[x][i]);
 50             x=fa[x][i];
 51         }
 52     if(x!=y)
 53     {
 54         for(i=lim;i>=0;i--)
 55         {
 56             if(fa[x][i]!=fa[y][i])
 57             {
 58                 ans=min(ans,min(mmin[x][i],mmin[y][i]));
 59                 x=fa[x][i];
 60                 y=fa[y][i];
 61             }
 62         }
 63         ans=min(ans,min(mmin[x][0],mmin[y][0]));
 64         x=fa[x][0];
 65         y=fa[y][0];
 66     }
 67     return ans;
 68 }
 69 int main()
 70 {
 71     int i,j;
 72     memset(head,-1,sizeof(head));
 73     memset(ans,-1,sizeof(ans));
 74     memset(mmin,127/3,sizeof(mmin));
 75     scanf("%d%d",&n,&m);lim=log2(n);
 76     for(i=1; i<=n; i++)father[i]=i;
 77     for(i=1; i<=m; i++)scanf("%d%d%d",&map[i].from,&map[i].to,&map[i].dis);
 78     sort(map+1,map+m+1,cmp);
 79     for(i=1; i<=m; i++)
 80     {
 81         int p=find(map[i].from),q=find(map[i].to);
 82         if(p!=q)
 83         {
 84             father[p]=q;
 85             putin(p,q,map[i].dis);
 86             putin(q,p,map[i].dis);
 87         }
 88     }
 89     scanf("%d",&l);
 90     for(i=1;i<=n;i++)if(father[i]==i)dfs(i,0);
 91     RMQ();
 92     for(i=1; i<=l; i++)
 93     {
 94         int from,to;
 95         scanf("%d%d",&from,&to);
 96         if(find(from)==find(to))printf("%d\n",LCA(from,to));
 97         else printf("-1\n");
 98     }
 99     return 0;
100 }

 

posted @ 2017-08-16 15:02  kakakakakaka  阅读(197)  评论(0编辑  收藏  举报

Never forget why you start

//鼠标爆炸特效