[NOIP2013]货车运输

嘟嘟嘟

首先,每一辆货车路径唯一,说明应该求生成树。又要满足这条路的最小边权最大,进一步得出要求最大生成树。

求完最大生成树上要解决的是树上任意两点之间的边权的最小值,我第一反应是树剖维护链上最小值,但其实我们用LCA就可以了:对于任意两点x, y, 维护x到LCA(x, y)和y到LCA(x, y)这两条链上的最小值。时间复杂度O(nlogn)。

还有几点要注意:

1.图并不连通,所以对于每一个没遍历过的点都要跑一遍LCA。

2.好像没啦。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const int INF = 0x3f3f3f3f;
 19 const db eps = 1e-8;
 20 const int maxn = 1e5 + 5;
 21 inline ll read()
 22 {
 23     ll ans = 0;
 24     char ch = getchar(), last = ' ';
 25     while(!isdigit(ch)) {last = ch; ch = getchar();}
 26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
 27     if(last == '-') ans = -ans;
 28     return ans;
 29 }
 30 inline void write(ll x)
 31 {
 32     if(x < 0) x = -x, putchar('-');
 33     if(x >= 10) write(x / 10);
 34     putchar(x % 10 + '0');
 35 }
 36 
 37 int n, m, q;
 38 vector<int> v[maxn], c[maxn];
 39 struct Edge
 40 {
 41     int x, y, co;
 42     bool operator < (const Edge& other)const
 43     {
 44         return co > other.co;
 45     }
 46 }e[maxn * 5];
 47 
 48 int p[maxn];
 49 void init(int n)
 50 {
 51     for(int i = 1; i <= n; ++i) p[i] = i;
 52 }
 53 int Find(int x)
 54 {
 55     return x == p[x] ? x : p[x] = Find(p[x]);
 56 }
 57 
 58 bool vis[maxn];
 59 int dep[maxn], fa[maxn][21], Min[maxn][21];
 60 void dfs(int now)
 61 {
 62     vis[now] = 1;
 63     for(int i = 1; (1 << i) <= dep[now]; ++i)
 64     {
 65         fa[now][i] = fa[fa[now][i - 1]][i - 1];
 66         Min[now][i] = min(Min[now][i - 1], Min[fa[now][i - 1]][i - 1]);
 67     }
 68     for(int i = 0; i < (int)v[now].size(); ++i)
 69     {
 70         if(!vis[v[now][i]])
 71         {
 72             dep[v[now][i]] = dep[now] + 1;
 73             fa[v[now][i]][0] = now;
 74             Min[v[now][i]][0] = c[now][i];
 75             dfs(v[now][i]);
 76         }
 77     }
 78 }
 79 int lca(int x, int y)
 80 {
 81     int ret = INF;
 82     if(dep[x] < dep[y]) swap(x, y);
 83     for(int i = 20; i >= 0; --i)
 84         if(dep[x] - (1 << i) >= dep[y])
 85         {
 86             if(Min[x][i] != 0)
 87             ret = min(ret, Min[x][i]);
 88             x = fa[x][i];
 89         }
 90     if(x == y) return ret;
 91     for(int i = 20; i >= 0; --i)
 92     {
 93         if(fa[x][i] != fa[y][i])
 94         {
 95             ret = min(ret, Min[x][i]);
 96             ret = min(ret, Min[y][i]);
 97             x = fa[x][i]; y = fa[y][i];
 98         }
 99     }
100     return min(ret, min(Min[x][0], Min[y][0]));
101 }
102 
103 int main()
104 {
105     n = read(); m = read();
106     init(n);
107     for(int i = 1; i <= m; ++i) e[i].x = read(), e[i].y = read(), e[i].co = read();
108     sort(e + 1, e + m + 1);
109     for(int i = 1, cnt = 0; i <= m; ++i)
110     {
111         int px = Find(e[i].x), py = Find(e[i].y);
112         if(px != py)
113         {
114             p[px] = py;
115             v[e[i].x].push_back(e[i].y); c[e[i].x].push_back(e[i].co);
116             v[e[i].y].push_back(e[i].x); c[e[i].y].push_back(e[i].co);
117             if(++cnt == n - 1) break;
118         }
119     }
120     for(int i = 1; i <= n; ++i) if(!vis[i]) dfs(i);    
121     q = read();
122     for(int i = 1; i <= q; ++i)
123     {
124         int x = read(), y = read();
125         if(Find(x) == Find(y)) write(lca(x, y)), enter;
126         else write(-1), enter;
127     }
128     return 0;
129 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9724100.html