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;
    }
  • 相关阅读:
    MySQL改动rootpassword的多种方法
    略论并行处理系统的日志设计
    ERROR (UnicodeEncodeError): 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128
    UnicodeEncodeError: 'ascii' codec can't encode character u'u65e0' in position 1: ordinal not in range(128)
    python -m json.tool 中文乱码 Format JSON with python
    CentOS6.6 zookeeper完全集群搭建
    libvirt kvm云主机监控
    glance image-create
    通过上一节部署出来的 Windows instance 有时候会发现操作系统时间总是慢 8 个小时,即使手工调整好时间和时区,下次 instance 重启后又会差 8 个小时
    云监控网址
  • 原文地址:https://www.cnblogs.com/candy99/p/5752827.html
Copyright © 2011-2022 走看看