货车运输

原题链接:https://www.luogu.org/problem/show?pid=1967

说出来你可能不信,这题我爆了一整天的0。想获取更多真相者,请打开洛谷p1967题评测界面,输入用户名“zx2000412”,你就知道现状有多惨烈。

先说说思路吧。听说这道题是最大生成树,我就按照这个思路往下展开的。

一开始的想法是跑一遍最大生成树,以获得的树的边再建一图,对于每次询问跑一次bfs。

后来发现时间复杂度是平方阶,肯定不是标算,只拿了5分(我不得不说,这题数据真心强

考虑到每次是在树上询问任意两点最大载重量,遂想到LCA做法。最后跑了380ms,差强人意。

听说树剖做法更快?改天试一下。

依然是要处理出最大生成树,存起来。用两个倍增数组,一个是f[i][j],代表从i这个点向上蹦2^j个点是哪个点,另一个是minval[i][j]代表从i向上蹦2^j个点时经过路径的最小值。

(求最大载重量为什么算最小?道理很显然啊,不可以超重,所以最大载重量一定是最小道路承载量)

求生成树是裸的Kruskal,并查集做法,这里不再赘述。细节部分详见代码。(这年头谁还用Prim)

然后是二次建图,这里有一步dfs预处理,把这个图转换成树一样的形式(虽然本来就是树)dep数组记录深度方便lca使用。

求LCA时也需要先预处理倍增数组,然后蹦的时候顺带维护一下ans就好。

参考代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define maxn 50005
  6 #define INF 888888888888
  7 using namespace std;
  8 typedef long long ll;
  9 //------------------------变量与结构体---------------------------
 10 ll dep[maxn],f[maxn][21],minval[maxn][21];
 11 ll n,m,q,x,y;
 12 ll tot = 0,head[maxn],father[maxn],fa[maxn];
 13 struct Edge{
 14     ll from,to,dis;
 15     bool operator<(const Edge& rhs)const{
 16         return dis > rhs.dis;
 17     }
 18 };
 19 Edge edge_T[maxn];
 20 Edge edge[maxn];
 21 //-------------------------辅助类函数-----------------------------
 22 ll read(){
 23     ll num = 0;
 24     char c;
 25     bool flag = false;
 26     while ((c = getchar()) == ' ' || c == '
' || c == '
');
 27     if (c == '-')
 28         flag = true;
 29     else
 30         num = c - '0';
 31     while (isdigit(c = getchar()))
 32         num = num * 10 + c - '0';
 33     return (flag ? -1 : 1) * num;
 34 }
 35 ll min_ele(ll a,ll b,ll c){
 36     ll t = min(a,b);
 37     return min(t,c);
 38 }
 39 //---------------------Kruskal与二次建图--------------------------
 40 
 41 void init_ufs(){
 42     for (register ll i=1;i<=n;i++)
 43         father[i] = i;
 44 }
 45 
 46 ll find(ll x){
 47     if (father[x] == x)
 48         return x;
 49     father[x] = find(father[x]);
 50     return father[x];
 51 }
 52 void merge(ll x, ll y){
 53     x = find(x);
 54     y = find(y);
 55     father[y] = x;
 56 }
 57 
 58 void add_edge(ll from,ll to,ll dis){
 59     edge[++tot].from = head[from];
 60     edge[tot].to = to;
 61     edge[tot].dis = dis;
 62     head[from] = tot;
 63 }
 64 void dfs(ll x){
 65     for (register ll i = head[x];i;i = edge[i].from){
 66         ll v = edge[i].to;
 67         if (v == fa[x])
 68             continue;      
 69         f[v][0] = x;
 70         minval[v][0] = edge[i].dis;
 71         dep[v] = dep[x] + 1;
 72         fa[v] = x;
 73         dfs(v);
 74     }
 75 }
 76 //--------------------------LCA相关------------------------------
 77 void init_lca(){
 78     for (register ll i=1;i<=20;i++)
 79         for (register ll j=1;j<=n;j++){
 80             f[j][i] = f[ f[j][i-1] ][i-1];
 81             minval[j][i] = min(minval[j][i-1],minval[ f[j][i-1] ][i-1]);
 82         }
 83 }
 84 ll lca(ll x,ll y){
 85     ll ans = INF;
 86     if (dep[x]>dep[y])
 87         swap(x,y);
 88     for (register ll i=20;i>=0;i--)
 89         if (dep[f[y][i]]>=dep[x]){
 90             ans=min(ans,minval[y][i]);
 91             y=f[y][i];
 92         }
 93     if (x==y)
 94         return ans;
 95     for (register ll i=20;i>=0;i--){
 96         if (f[x][i] != f[y][i]){
 97             ans = min_ele(minval[x][i],minval[y][i],ans);
 98             x = f[x][i];
 99             y = f[y][i];
100         }
101     }
102     ans = min_ele(minval[x][0],minval[y][0],ans);
103     return ans;
104 }
105 //----------------------------主函数----------------------------
106 int main(){
107     n = read();m = read();
108     for (register ll i=1;i<=m;i++){
109         edge_T[i].from = read();
110         edge_T[i].to = read();
111         edge_T[i].dis = read();
112     }
113     sort(edge_T+1,edge_T+m+1);
114     init_ufs();
115     for (register ll i=1;i<=m;i++)
116         if (find(edge_T[i].from) != find(edge_T[i].to)){
117             merge(edge_T[i].from,edge_T[i].to);
118             add_edge(edge_T[i].from, edge_T[i].to, edge_T[i].dis);
119             add_edge(edge_T[i].to, edge_T[i].from, edge_T[i].dis);
120         }
121     for (register ll i=1;i<=n;i++)
122         if (father[i] == i){
123             fa[i] = i;dep[i] = 1;dfs(i);
124         }
125     init_lca();
126     q = read();
127     for (register ll i=1;i<=q;i++){
128         x = read();y = read();
129         if (find(x) == find(y))
130                printf("%lld
",lca(x,y));
131         else
132             printf("-1
");
133     }
134     return 0;
135 }
原文地址:https://www.cnblogs.com/OIerShawnZhou/p/7636253.html