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

    题目描述

    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<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<stack>
      9 #include<queue>
     10 #include<map>
     11 #define RG register
     12 #define IL inline
     13 #define pi acos(-1.0)
     14 #define ll long long
     15 #define ls x<<1
     16 #define rs x<<1|1
     17 #define MID int mid=(l+r)>>1;
     18 #define inf 1<<30
     19 using namespace std;
     20 
     21 const int maxn = 10010;
     22 const int maxm = 50010;
     23 
     24 int gi() {
     25   char ch=getchar(); int x=0;
     26   while(ch<'0' || ch>'9') ch=getchar();
     27   while(ch>='0' && ch<='9') {x=10*x+ch-'0';ch=getchar();}
     28   return x;
     29 }
     30 
     31 int n,m,k,z,q,fa[maxm];
     32 int nxt[maxm*2],to[maxm*2],dis[maxm*2],h[maxn],e_num;
     33 int siz[maxn],son[maxn],top[maxn],dep[maxn],fat[maxn],w[maxn],dfn[maxn],rev[maxn];
     34 int tr[maxn*4];
     35 bool bj[maxn];
     36 struct EDGE {
     37   int x,y,v;
     38 }e[maxm],E[maxm];
     39 
     40 bool cmp(EDGE a, EDGE b) {
     41   return a.v>b.v;
     42 }
     43 
     44 int find(int x) {
     45   if(fa[x]!=x) fa[x]=find(fa[x]);
     46   return fa[x];
     47 }
     48 
     49 void add(int x, int y, int v) {
     50   nxt[++e_num]=h[x];
     51   to[e_num]=y;
     52   dis[e_num]=v;
     53   h[x]=e_num;
     54 }
     55 
     56 void dfs1(int u) {
     57   siz[u]=1;
     58   for(int i=h[u]; i; i=nxt[i]) {
     59     int v=to[i];
     60     if(v==fat[u]) continue;
     61     fat[v]=u;
     62     dep[v]=dep[u]+1;
     63     w[v]=dis[i];
     64     dfs1(v);
     65     if(siz[v]>siz[son[u]]) son[u]=v;
     66     siz[u]+=siz[v];
     67   }
     68 }
     69 
     70 void dfs2(int u) {
     71   dfn[u]=++z;rev[z]=u;
     72   if(son[u]) top[son[u]]=top[u],dfs2(son[u]);
     73   for(int i=h[u]; i; i=nxt[i]) {
     74     int v=to[i];
     75     if(v==fat[u] || v==son[u]) continue;
     76     top[v]=v,dfs2(v);
     77   }
     78 }
     79 
     80 void build(int x, int l, int r) {
     81   if(l==r) {tr[x]=w[rev[l]];return;}
     82   MID;
     83   build(ls,l,mid),build(rs,mid+1,r);
     84   tr[x]=min(tr[ls],tr[rs]);
     85 }
     86 
     87 int query(int x, int l, int r, int ql, int qr) {
     88   if(l>=ql && r<=qr) return tr[x];
     89   MID;
     90   if(qr<=mid) return query(ls,l,mid,ql,qr);
     91   else if(ql>mid) return query(rs,mid+1,r,ql,qr);
     92   return min(query(ls,l,mid,ql,mid),query(rs,mid+1,r,mid+1,qr));
     93 }
     94 
     95 int lca(int x, int y) {
     96   int tmp=inf;
     97   while(top[x]!=top[y]) {
     98     if(dep[top[x]]>dep[top[y]]) tmp=min(tmp,query(1,1,z,dfn[top[x]],dfn[x])),x=fat[top[x]];
     99     else tmp=min(tmp,query(1,1,z,dfn[top[y]],dfn[y])),y=fat[top[y]];
    100   }
    101   if(x==y) return tmp;
    102   else {
    103     if(dep[x]>dep[y]) swap(x,y);
    104     tmp=min(tmp,query(1,1,z,dfn[x]+1,dfn[y]));
    105   }
    106   return tmp;
    107 }
    108 
    109 int main() {
    110   n=gi(),m=gi();
    111   for(int i=1; i<=m; i++) {
    112     E[i].x=gi(),E[i].y=gi(),E[i].v=gi();
    113     fa[i]=i;
    114   }
    115   sort(E+1,E+m+1,cmp);
    116   for(int i=1; i<=m; i++) {
    117     int x=find(E[i].x),y=find(E[i].y);
    118     if(x==y) continue;
    119     e[++k].x=E[i].x,e[k].y=E[i].y,e[k].v=E[i].v;
    120     fa[y]=x;
    121     if(k==n-1) break;
    122   }
    123   for(int i=1; i<=k; i++) {
    124     bj[e[i].x]=1,bj[e[i].y]=1;
    125     add(e[i].x,e[i].y,e[i].v);
    126     add(e[i].y,e[i].x,e[i].v);
    127   }
    128   dep[1]=1,fat[1]=1,top[1]=1,w[1]=inf;
    129   dfs1(1),dfs2(1),build(1,1,z);
    130   q=gi();
    131   for(int i=1; i<=q; i++) {
    132     int x=gi(),y=gi();
    133     if(!bj[x] || !bj[y]) printf("-1
    ");
    134     else printf("%d
    ", lca(x,y));
    135   }
    136 }

    总结——图上最小(大)边的最大(小)化问题

    1、路径上最小边的最大值:最大生成树+树链最小值

    2、路径上最大边的最小值:最小生成树+树链最大值

  • 相关阅读:
    UWP中的消息提示框(二)
    UWP中的消息提示框(一)
    使用批处理编写ORACLE设置
    程序员那些事儿
    “程序已停止工作”问题的解决方法
    《第一行代码--Android》阅读笔记之数据持久化
    《第一行代码--Android》阅读笔记之广播
    《第一行代码--Android》阅读笔记之界面设计
    《第一行代码--Android》阅读笔记之Activity
    WinForm中为按钮添加键盘快捷键,超简单,亲测有效
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7229319.html
Copyright © 2011-2022 走看看