zoukankan      html  css  js  c++  java
  • NOIP2013货车运输[lca&&kruskal]

    题目描述

    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

    说明

    对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。

    ------------------------------------------------------------------------------------------------------------------------------

    和《训练指南》上第五章例题21(uva11354 bond)很像。。。

    最小瓶颈生成树,最小瓶颈路现求出最大生成树,树上的路径一定是权值最大的,变有根然后在这上面找lca

    白书上要两遍dfs,其实一遍即可,dfs前先维护fa[][]和cost[][]。

    查询有两种做法,白书上是lca和查询在一起,也可以先求lca,再求两个点到他们的lca的最小值,取min。

    关于倍增,16是上界,(1<<16)=  65536

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 using namespace std;
      6 const int N=10005,M=50005,INF=1e9;
      7 int read(){
      8     char c=getchar();int x=0,f=1;
      9     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     10     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     11     return x;
     12 }
     13 
     14 int n,m,q,x,y;
     15 //graph
     16 struct etmp{        //just tmp
     17     int u,v,w;
     18 }a[M];
     19 struct edge{
     20     int u,v,w,ne;   //u is not needed
     21 }e[N*2];
     22 int h[N],cnt=0;
     23 inline void add(int u,int v,int w){
     24     cnt++;
     25     e[cnt].u=u; e[cnt].v=v; e[cnt].w=w;
     26     e[cnt].ne=h[u]; h[u]=cnt;
     27 }
     28 inline void ins(int u,int v,int w){
     29     add(u,v,w);
     30     add(v,u,w);
     31 }
     32 bool cmp(etmp &a,etmp &b){return a.w>b.w;}
     33 
     34 //kruskal
     35 int p[N];
     36 int findp(int x){return x==p[x]?x:p[x]=findp(p[x]);}
     37 
     38 void kruskal(){
     39     sort(a+1,a+1+m,cmp);
     40     int num=0;
     41     for(int i=1;i<=n;i++) p[i]=i;
     42     for(int i=1;i<=m;i++){
     43         int x=findp(a[i].u),y=findp(a[i].v);
     44         if(x==y) continue;
     45         p[x]=y;
     46         num++;
     47         ins(a[i].u,a[i].v,a[i].w);
     48         if(num==n-1) break;
     49     }
     50 }
     51 
     52 //lca
     53 int fa[N][20],cost[N][20],deep[N];  // all[root]=0  //deep<-->the number of ancient
     54 bool vis[N];
     55 void dfs(int u){
     56     vis[u]=true;
     57     
     58     for(int j=1;(1<<j)<=deep[u];j++){   //update
     59         int tmp=fa[u][j-1];
     60         fa[u][j]=fa[tmp][j-1];
     61         cost[u][j]=min(cost[u][j-1],cost[tmp][j-1]);
     62     }
     63     
     64     for(int i=h[u];i;i=e[i].ne){        //dfs
     65         int v=e[i].v,w=e[i].w;
     66         if(!vis[v]){
     67             fa[v][0]=u;
     68             cost[v][0]=w;
     69             deep[v]=deep[u]+1;
     70             dfs(v);
     71         }
     72     }
     73 }
     74 
     75 int lca(int x,int y){
     76     if(deep[x]<deep[y]) swap(x,y);  //dx>dy
     77     int bin=deep[x]-deep[y];
     78     for(int i=0;i<=16;i++)          //same deep
     79         if((1<<i)&bin) x=fa[x][i];
     80     
     81     for(int i=16;i>=0;i--)          //pull up
     82         if(fa[x][i]!=fa[y][i]){     //0==0
     83             x=fa[x][i];
     84             y=fa[y][i];
     85         }
     86     if(x==y) return x;
     87     else return fa[x][0];
     88 }
     89 
     90 int query(int x,int f){
     91     int mn=INF;
     92     int bin=deep[x]-deep[f];
     93     
     94     for(int i=0;i<=16;i++)
     95         if((1<<i)&bin){
     96             mn=min(mn,cost[x][i]);
     97             x=fa[x][i];
     98         }
     99     return mn;
    100 }
    101 int main(){
    102     n=read(); m=read();
    103     for(int i=1;i<=m;i++){
    104         a[i].u=read();a[i].v=read();a[i].w=read();
    105     }
    106     kruskal();
    107     for(int i=1;i<=n;i++)
    108         if(!vis[i]) dfs(i);
    109     
    110     q=read();
    111     for(int i=1;i<=q;i++){
    112         x=read();y=read();
    113         if(findp(x)!=findp(y)){
    114             printf("-1
    ");continue;
    115         }else{
    116             int f=lca(x,y);
    117             printf("%d
    ",min(query(x,f),query(y,f)));
    118         }
    119     }
    120     
    121 }

    白书的查询

    int lca2(int x,int y){
        int mn=INF;
        
        if(deep[x]<deep[y]) swap(x,y);
        int bin=deep[x]-deep[y];
        for(int i=0;i<=16;i++)
            if(bin&(1<<i)){
                mn=min(mn,cost[x][i]);
                x=fa[x][i];
            }
        if(x==y) return mn;
        
        for(int i=16;i>=0;i--)
            if(fa[x][i]!=fa[y][i]){     //fa[x][i]!=0 is not needed cause deep-> 0==0
                mn=min(mn,cost[x][i]);x=fa[x][i];
                mn=min(mn,cost[y][i]);y=fa[y][i];
            }
        
        mn=min(mn,cost[x][0]);
        mn=min(mn,cost[y][0]);
        return mn;
    }
  • 相关阅读:
    cnblog项目--20190309
    django js引入失效问题
    Python老男孩 day16 函数(六) 匿名函数
    Python老男孩 day16 函数(五) 函数的作用域
    Python老男孩 day15 函数(四) 递归
    Python老男孩 day15 函数(三) 前向引用之'函数即变量'
    Python老男孩 day15 函数(二) 局部变量与全局变量
    Python老男孩 day14 函数(一)
    Python老男孩 day14 字符串格式化
    Python老男孩 day14 集合
  • 原文地址:https://www.cnblogs.com/candy99/p/5752827.html
Copyright © 2011-2022 走看看