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

    Description

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

    Input

    输入文件名为 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

    Output

    输出文件名为 truck.out。

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

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

    Sample Input

    4 3
    1 2 4
    2 3 3
    3 1 1
    3
    1 3
    1 4
    1 3

    Sample Output

    3
    -1
    3

    Hint

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

    题解

    $Kruskal$+$LCA$+并查集
        建最大生成森林(以保证联通性的情况下最大化瓶颈路径)。
        并查集判断是否联通。
        若联通,$LCA$出路径上的最短边。

      1 #include<map>
      2 #include<ctime>
      3 #include<cmath>
      4 #include<queue>
      5 #include<stack>
      6 #include<cstdio>
      7 #include<string>
      8 #include<vector>
      9 #include<cstring>
     10 #include<cstdlib>
     11 #include<iostream>
     12 #include<algorithm>
     13 #define LL long long
     14 #define RE register
     15 #define IL inline
     16 using namespace std;
     17 const int N=10000;
     18 const int M=50000;
     19 
     20 IL int Min(const int &a,const int &b) {return a<b ? a:b;}
     21 
     22 int n,m,q,lim,x,y;
     23 struct tt
     24 {
     25     int from,to,cost;
     26 }lin[M+5];
     27 IL bool comp(const tt &a,const tt &b) {return a.cost>b.cost;}
     28 
     29 int set[N+5];
     30 IL int Find(int r) {return set[r] ? set[r]=Find(set[r]):r;}
     31 IL void Kruskal();
     32 
     33 struct ss
     34 {
     35     int to,next,cost;
     36 }edge[N*2+5];
     37 int path[N+5],top;
     38 IL void Add(int u,int v,int c);
     39 
     40 bool vis[N+5];
     41 int fa[N+5][15],minn[N+5][15],dep[N+5];
     42 void Dfs(int r,int depth);
     43 IL void RMQ();
     44 
     45 IL int LCA(int x,int y);
     46 
     47 int main()
     48 {
     49     scanf("%d%d",&n,&m);lim=log2(n);
     50     for (RE int i=1;i<=m;i++) scanf("%d%d%d",&lin[i].from,&lin[i].to,&lin[i].cost);
     51     Kruskal();
     52     for (RE int i=1;i<=n;i++) if (!vis[i]) Dfs(i,1);
     53     RMQ();
     54     scanf("%d",&q);
     55     while (q--)
     56     {
     57         scanf("%d%d",&x,&y);
     58         int a=Find(x);
     59         int b=Find(y);
     60         if (a!=b) printf("-1
    ");
     61         else printf("%d
    ",LCA(x,y));
     62     }
     63     return 0;
     64 }
     65 
     66 IL void Kruskal()
     67 {
     68     sort(lin+1,lin+m+1,comp);
     69     int cnt=0;
     70     for (RE int i=1;i<=m;i++)
     71     {
     72         int q=Find(lin[i].from);
     73         int p=Find(lin[i].to);
     74         if (p!=q)
     75         {
     76             set[p]=q;
     77             cnt++;
     78             Add(lin[i].from,lin[i].to,lin[i].cost);
     79             Add(lin[i].to,lin[i].from,lin[i].cost);
     80             if (cnt==n-1) break;
     81         }
     82     }
     83 }
     84 IL void Add(int u,int v,int c)
     85 {
     86     edge[++top].to=v;
     87     edge[top].next=path[u];
     88     edge[top].cost=c;
     89     path[u]=top;
     90 }
     91 void Dfs(int r,int depth)
     92 {
     93     vis[r]=1;
     94     dep[r]=depth;
     95     for (RE int i=path[r];i;i=edge[i].next) if (!vis[edge[i].to])
     96     {
     97         fa[edge[i].to][0]=r;
     98         minn[edge[i].to][0]=edge[i].cost;
     99         Dfs(edge[i].to,depth+1);
    100     }
    101 }
    102 IL void RMQ()
    103 {
    104     for (RE int t=1;t<=lim;t++)
    105         for (RE int i=1;i<=n;i++)
    106         {
    107             fa[i][t]=fa[fa[i][t-1]][t-1];
    108             minn[i][t]=Min(minn[i][t-1],minn[fa[i][t-1]][t-1]);
    109         }
    110 }
    111 IL int LCA(int x,int y)
    112 {
    113     int ans=2e9;
    114     if (dep[x]<dep[y]) swap(x,y);
    115     for (RE int i=lim;i>=0;i--) if (dep[x]-(1<<i)>=dep[y])
    116     {
    117         ans=Min(ans,minn[x][i]);
    118         x=fa[x][i];
    119     }
    120     if (x!=y)
    121     {
    122         for (RE int i=lim;i>=0;i--) if (fa[x][i]!=fa[y][i])
    123         {
    124             ans=Min(ans,minn[x][i]);
    125             ans=Min(ans,minn[y][i]);
    126             x=fa[x][i];
    127             y=fa[y][i];
    128         }
    129         ans=Min(ans,minn[x][0]);
    130         ans=Min(ans,minn[y][0]);
    131         x=fa[x][0];
    132         y=fa[y][0];
    133     }
    134     return ans;
    135 }
  • 相关阅读:
    银行卡号每隔4位插入空格
    IE6-8下自定义标签的表现
    Sql Server尝试读取或写入受保护的内存。这通常指示其他内存已损坏
    儿童编程教学scratch 3.0
    Shell 教程入门
    自定义vs2005代码段
    解决Adobe ReaderXI自动关闭问题
    WPF——给button添加背景图片
    WPF 异步加载数据
    Caliburn.Micro中的WindowManager
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7366014.html
Copyright © 2011-2022 走看看