NOIp 2013 Day1T3 货车运输

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

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。


 

方法一: 最大生成树 + 树上倍增,代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int maxn = 10000 + 5;
  8 const int maxm = 100000 + 5;
  9 struct Edge
 10 {
 11     int f, t, v;
 12     bool operator < (const Edge a) const
 13     {
 14         return v > a.v;
 15     }
 16 }gra[maxm], edg[maxm];
 17 int n, m, q, u;
 18 int fir[maxn], nxt[maxn << 1], fa[maxn];
 19 int dep[maxn], p[maxn][21], minn[maxn][21];
 20 bool used[maxn];
 21 void Build(int, int, int), Kruskal_hu(), DFS(int), Pre_lca();
 22 int Ask_lca(int, int), Ask_ans(int, int, int), Find(int);
 23 
 24 int main()
 25 {
 26     memset(fir, -1, sizeof(fir));
 27     memset(minn, 0x7f, sizeof(minn));
 28     scanf("%d%d", &n, &m);
 29     for(int i = 0; i < m; i++)
 30     {
 31         int f, t, v;
 32         scanf("%d%d%d", &f, &t, &v);
 33         edg[i] = (Edge){f, t, v};
 34     }
 35     Kruskal_hu();
 36     DFS(1);
 37     Pre_lca();
 38     scanf("%d", &q);
 39     while(q--)
 40     {
 41         int x, y;
 42         scanf("%d%d", &x, &y);
 43         if(Find(x) != Find(y)) puts("-1");
 44         else
 45         {
 46             int lca = Ask_lca(x, y);
 47             printf("%d\n", Ask_ans(x, lca, y));
 48         }
 49     }
 50     return 0;
 51 }
 52 
 53 int Ask_ans(int x, int pa, int y)
 54 {
 55     int ans = 1e9 + 7;
 56     int f = dep[x] - dep[pa];
 57     for(int i = 20; i >= 0; i--)
 58         if((1 << i)&f)
 59         {
 60             ans = min(ans, minn[x][i]);
 61             x = p[x][i];
 62         }
 63     f = dep[y] - dep[pa];
 64     for(int i = 20; i >= 0; i--)
 65         if((1 << i)&f)
 66         {
 67             ans = min(ans, minn[y][i]);
 68             y = p[y][i];
 69         }
 70     return ans;
 71 }
 72 
 73 void Pre_lca()
 74 {
 75     for(int j = 1; (1 << j) <= n; j++)
 76         for(int i = 1; i <= n; i++)
 77         {
 78             p[i][j] = p[p[i][j - 1]][j - 1];
 79             minn[i][j] = min(minn[i][j - 1], minn[p[i][j - 1]][j - 1]);
 80         }
 81 }
 82 
 83 void DFS(int k)
 84 {
 85     used[k] = 1;
 86     for(int i = fir[k]; ~i; i = nxt[i])
 87     {
 88         int tmp = gra[i].t;
 89         if(used[tmp]) continue;
 90         p[tmp][0] = k;
 91         dep[tmp] = dep[k] + 1;
 92         minn[tmp][0] = gra[i].v;
 93         DFS(tmp);
 94     }
 95 }
 96 
 97 int Ask_lca(int x, int y)
 98 {
 99     if(dep[x] > dep[y]) swap(x, y);
100     int f = dep[y] - dep[x];
101     for(int i = 0; (1 << i) <= f; i++)
102         if((1 << i)&f) y = p[y][i];
103     if(x != y)
104     {
105         for(int i = 20; i >= 0; i--)
106             if(p[x][i] != p[y][i])
107             {
108                 x = p[x][i];
109                 y = p[y][i];
110             }
111         x = p[x][0];
112     }
113     return x;
114 }
115 
116 void Build(int f, int t, int v)
117 {
118     gra[++u] = (Edge){f, t, v};
119     nxt[u] = fir[f], fir[f] = u;
120     gra[++u] = (Edge){t, f, v};
121     nxt[u] = fir[t], fir[t] = u;
122 }
123 
124 int Find(int x)
125 {
126     return fa[x] == x ? x : fa[x] = Find(fa[x]);
127 }
128 
129 void Kruskal_hu()
130 {
131     for(int i = 1; i <= n; i++) fa[i] = i;
132     sort(edg, edg + m);
133     for(int i = 0; i < m; i++)
134     {
135         int x = Find(edg[i].f), y = Find(edg[i].t);
136         if(x != y)
137         {
138             Build(edg[i].f, edg[i].t, edg[i].v);
139             fa[x] = y;
140         }
141     }
142 }
MLT + LCA

方法二:树链剖分 + 线段树,各种错误,弃坑

 

转载于:https://www.cnblogs.com/DreifxP/p/7741134.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值