卧薪尝胆,厚积薄发。
NOIP2013D1T3 货车运输
Date: Sun Sep 02 00:06:29 CST 2018 In Category: NoCategory

Description:

$n$ 个点, $m$ 条无向边,每条边有限重,多次询问从 $a$ 到 $b$ 一次最多能运多少货物。
$1\le n \le 10000$

Solution:

显然路径一定在最大生成树上,于是先求出最大生成树,就变成了路径边权最小值,树剖倍增 $LCT$ 都可以。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cstring>
using namespace std;
int n,m,q;
#define MAXN 100010
#define MAXM 500010
struct edge
{
int u,v,w;
}e[MAXM];
bool cmp_s(edge x,edge y){return x.w > y.w;}
int f[MAXN];
int find(int x){return (f[x] == 0 ? x : f[x] = find(f[x]));}
#define INF 0x3f3f3f3f
struct node
{
int c[2],fa,v,mx;
bool rev;
node(){v = mx = INF;rev = false;}
}t[MAXN + MAXM];
void maintain(int k){t[k].mx = min(t[k].v,min(t[t[k].c[0]].mx,t[t[k].c[1]].mx));return;}
void pushdown(int rt)
{
if(t[rt].rev)
{
t[t[rt].c[0]].rev ^= 1;t[t[rt].c[1]].rev ^= 1;
swap(t[rt].c[0],t[rt].c[1]);t[rt].rev = false;
}
return;
}
int id(int k){return (t[t[k].fa].c[0] == k ? 0 : 1);}
void connect(int k,int f,int p){t[k].fa = f;t[f].c[p] = k;return;}
bool isroot(int k){return (t[t[k].fa].c[0] != k && t[t[k].fa].c[1] != k);}
void rotate(int x)
{
int y = t[x].fa,z = t[y].fa,fx = id(x),fy = id(y);
if(!isroot(y))t[z].c[fy] = x;
t[x].fa = z;
connect(t[x].c[fx ^ 1],y,fx);
connect(y,x,fx ^ 1);
maintain(y);maintain(x);
return;
}
stack<int> s;
void splay(int x)
{
s.push(x);
for(int i = x;!isroot(i);i = t[i].fa)s.push(t[i].fa);
while(!s.empty()){pushdown(s.top());s.pop();}
while(!isroot(x))
{
int y = t[x].fa;
if(isroot(y)){rotate(x);break;}
if(id(x) == id(y)){rotate(y);rotate(x);}
else{rotate(x);rotate(x);}
}
return;
}
void access(int k){for(int i = 0;k;i = k,k = t[k].fa){splay(k);t[k].c[1] = i;maintain(k);}return;}
void makeroot(int k){access(k);splay(k);t[k].rev ^= 1;return;}
void link(int x,int y){makeroot(x);t[x].fa = y;return;}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;++i)
{
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
sort(e + 1,e + 1 + m,cmp_s);
for(int i = 1;i <= m;++i)
{
if(find(e[i].u) != find(e[i].v))
{
f[find(e[i].u)] = find(e[i].v);
t[i + n].v = t[i + n].mx = e[i].w;
link(e[i].u,i + n);
link(e[i].v,i + n);
}
}
scanf("%d",&q);
int a,b;
for(int i = 1;i <= q;++i)
{
scanf("%d%d",&a,&b);
if(find(a) != find(b))
{
puts("-1");
continue;
}
makeroot(a);access(b);splay(b);
printf("%d\n",t[b].mx);
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡