zoukankan      html  css  js  c++  java
  • 洛谷 P1967 货车运输 Label: 倍增LCA && 最小瓶颈路

    题目描述

    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。

    代码

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #define LEN 100005
      7 #define LOG_LEN 25
      8 #define ll long long
      9 #define INF 0x3f3f3f3f
     10 using namespace std;
     11 
     12 int n,m;
     13 int fa[LEN],parent[LOG_LEN][LEN],dep[LEN];
     14 ll dis[LOG_LEN][LEN];
     15 
     16 struct PA{ll num,d;};//pair
     17 PA make_PA(ll num,ll d){PA tmp;tmp.num=num;tmp.d=d;return tmp;}
     18 struct edge{int from,to;ll val;}e[LEN];
     19 bool cmp(edge a,edge b){return a.val>b.val;}//最大值优先
     20 
     21 //BingChaJi ,没有rank版本 
     22 void init_BingChaJi(){for(int i=0;i<LEN;i++) fa[i]=i;}
     23 int Find(int a){if(fa[a]==a) return a;else return fa[a]=Find(fa[a]);}
     24 void Unite(int a,int b){int pa=Find(a),pb=Find(b);if(pa!=pb) fa[pa]=pb;}
     25 
     26 vector<PA> Map[LEN];
     27 
     28 void Kruskal(){//最大生成树 
     29     sort(e,e+m,cmp);
     30     init_BingChaJi();
     31     int cnt=0;
     32     for(int i=0;i<m;i++){
     33         int a=e[i].from,b=e[i].to;ll v=e[i].val;
     34         if(Find(a)==Find(b))continue;
     35         Unite(a,b);
     36         Map[a].push_back(make_PA(b,v));
     37         Map[b].push_back(make_PA(a,v));
     38         cnt++;
     39         if(cnt==n-1) return;
     40     }
     41 }
     42 
     43 void dfs(int v,int f,int d){
     44     parent[0][v]=f;
     45     dis[0][v]=INF;
     46     dep[v]=d;
     47     for(int i=0;i<Map[v].size();i++){
     48         PA now=Map[v][i];
     49         if(now.num!=f) dfs(now.num,v,d+1);
     50         else dis[0][v]=now.d;
     51     }
     52 }
     53 
     54 void init_lca(){
     55     memset(dis,INF,sizeof(dis));
     56     memset(dep,-1,sizeof(dep));
     57     for(int i=1;i<=n;i++) if(dep[i]<0) dfs(i,-1,0);
     58     for(int k=0;k+1<LOG_LEN;k++){
     59         for(int i=1;i<=n;i++){
     60             if(parent[k][i]<0) parent[k+1][i]=-1 , dis[k+1][i] = INF;
     61             else{
     62                 parent[k+1][i]=parent[k][ parent[k][i] ];
     63                 dis[k+1][i]=min(dis[k][i],dis[k][ parent[k][i] ]);
     64             }
     65         }
     66     }
     67 }
     68 
     69 ll lca(int u,int v){
     70     if(dep[v]>dep[u]) swap(u,v);
     71     ll res=INF;
     72     for(int i=0;i<LOG_LEN;i++){
     73         if( ( (dep[u]-dep[v]) >> i) & 1 ){
     74             res=min(res,dis[i][u]);
     75             u=parent[i][u];
     76         }
     77     }
     78     if(u==v) return res;
     79     
     80     for(int i=LOG_LEN-1;i>=0;i--){//这里没有-1会WA 
     81         if(parent[i][u]!=parent[i][v]){
     82             res=min(res,dis[i][u]);
     83             res=min(res,dis[i][v]);
     84             u=parent[i][u];v=parent[i][v];
     85         }
     86     }
     87     res=min(res,dis[0][u]);
     88     res=min(res,dis[0][v]);
     89     return res;
     90 }
     91 
     92 int main(){
     93 //    freopen("01.in","r",stdin);
     94 //    freopen("01.out","w",stdout);
     95     
     96     scanf("%d%d",&n,&m);
     97     for(int i=0;i<m;i++) scanf("%d%d%lld",&e[i].from,&e[i].to,&e[i].val);
     98     
     99     Kruskal();
    100     init_lca();
    101     
    102     int kase=0;
    103     scanf("%d",&kase);
    104     while(kase--){
    105         int u,v;
    106         scanf("%d%d",&u,&v);
    107         if(Find(u)==Find(v)) printf("%lld
    ",lca(v,u));//查找是否同一组 
    108         else puts("-1");
    109     }
    110     return 0;
    111 }

    貌似要用long long

    注意Line 80

    还有就是我zz了,Line 24

    void Unite(int a,int b){int pa=Find(a),pb=Find(b);if(pa!=pb) fa[pa]=pb;}

    写成pa==pb,Orz……

    抄个代码都花了这么久。。。

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 相关阅读:
    获取MAC地址的两种方法
    发现使用wcf传输的文件有20K的丢失
    用 document.readyState == "complete" 判断页面是否加载完成。
    防止SQL注入ASP代码
    什么是极端编程?
    Web.config 节点含义
    去掉网页上的图片工具栏
    程序员—青春饭?
    历史大骗局:广岛长崎原子弹爆炸
    最佳实践
  • 原文地址:https://www.cnblogs.com/radiumlrb/p/5859759.html
Copyright © 2011-2022 走看看