您的位置:首页 > 其它

NOIp2013提高组 货车运输

2019-09-23 22:54 106 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_41996523/article/details/101231879

文章目录

题目链接

LGOJ P1967 货车运输

解题思路

一开始我觉得这题很难,然后觉得越做越简单。。。
我们要求每个货车的最大载重,就是要使货车走过的边权中的最小值尽可能大。我们发现,货车一定会走每个联通块内的最大生成树
于是我先Kruskal一遍最大生成树,得到了一片森林。
我们考虑如何处理询问:

  • 我们如果发现询问的两个点不在同一个联通块内(可根据Kruskal中的并查集判断),那么显然,输出-1。
  • 如果在一个联通块内,我们可以使用倍增的算法来求出路径中的最小权值(有点像LCA)

详细代码

#define USEFASTERREAD 1

#define rg register
#define inl inline
#define DEBUG printf("qwq\n")
#define DEBUGd(x) printf("var %s is %lld", #x, ll(x))
#define DEBUGf(x) printf("var %s is %llf", #x, double(x))
#define putln putchar('\n')
#define putsp putchar(' ')
#define Rep(a, s, t) for(rg int a = s; a <= t; a++)
#define Repdown(a, t, s) for(rg int a = t; a >= s; a--)
typedef long long ll;
typedef unsigned long long ull;
#include<cstdio>

#if USEFASTERREAD
char In[1 << 20], *ss = In, *tt = In;
#define getchar() (ss == tt && (tt = (ss = In) + fread(In, 1, 1 << 20, stdin), ss == tt) ? EOF : *ss++)
#endif
namespace IO {
inl void RS() {freopen("test.in", "r", stdin), freopen("test.out", "w", stdout);}
inl ll read() {
ll x = 0, f = 1; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + int(ch - '0');
return x * f;
}
inl void write(ll x) {
if(x < 0) {putchar('-'); x = -x;}
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
inl void writeln(ll x) {write(x), putln;}
inl void writesp(ll x) {write(x), putsp;}
}
using namespace IO;
template<typename T> inline T Max(const T& x, const T& y) {return y < x ? x : y;}
template<typename T> inline T Min(const T& x, const T& y) {return y < x ? y : x;}
template<typename T> inline void Swap(T& x, T& y) {T tmp = x; x = y; y = tmp;}
template<typename T> inline T Abs(const T& x) {return x < 0 ? -x : x;}
#include<algorithm>
#include<cstring>
const int MAXN = 1e4 + 5;
const int MAXM = 5e4 + 5;
const int INF = 0x3f3f3f3f;
int n, m;
namespace Part2 {//跑lca
struct Edge {
int v, nxt, w;
}e[MAXM << 1];
int cnt, head[MAXN];
void addedge(int u, int v, int w) {
e[++cnt].w = w;
e[cnt].v = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
}
namespace Part1 {//最大生成树
struct Edge {
int u, v, w;
bool operator < (const Edge& x)const {
return w > x.w;
}
}e[MAXM];
int cnt;
void addedge(int u, int v, int w) {
e[++cnt].u = u; e[cnt].v = v; e[cnt].w = w;
}
int fa[MAXN];
int getfa(int x) {return x == fa[x] ? x : fa[x] = getfa(fa[x]);}
void Kruskal() {
for(rg int i = 1; i <= n; i++) fa[i] = i;
std::sort(e + 1, e + 1 + cnt);
for(rg int i = 1; i <= cnt; i++) {
int fu = getfa(e[i].u), fv = getfa(e[i].v);
if(fu == fv) continue;
Part2::addedge(e[i].u, e[i].v, e[i].w);
Part2::addedge(e[i].v, e[i].u, e[i].w);
fa[fu] = fv;
}
}
}
namespace Part2 {
int dep[MAXN], fa[MAXN][21], dis[MAXN][21], vist[MAXN], lg[MAXN];
void dfs(int u, int f, int w) {
if(vist[u]) return;
vist[u] = true;
dep[u] = dep[f] + 1;
dis[u][0] = w;
fa[u][0] = f;
for(rg int i = 1; (1 << i) <= dep[u]; i++) {
fa[u][i] = fa[fa[u][i - 1]][i - 1];
dis[u][i] = Min(dis[u][i - 1], dis[fa[u][i - 1]][i - 1]);
}
for(rg int i = head[u]; i; i = e[i].nxt) {
if(e[i].v != f) dfs(e[i].v, u, e[i].w);
}
}
void init() {
memset(dis, 0x3f, sizeof dis);
lg[0] = -1;
for(rg int i = 1; i <= n; i++) lg[i] = lg[i >> 1] + 1;
for(rg int i = 1; i <= n; i++)
if(!vist[i]) dfs(i, 0, INF);
}

using Part1::getfa;
int LCA(int a, int b) {
if(getfa(a) != getfa(b)) return -1;
int ans = INF;
if(dep[a] < dep[b]) Swap(a, b);
while(dep[a] > dep[b]) {
int stp = lg[dep[a] - dep[b]];
ans = Min(ans, dis[a][stp]);
a = fa[a][stp];
}
if(a == b) return ans;
for(rg int i = lg[dep[a]]; i >= 0; i--)
if(fa[a][i] != fa[b][i]) {
ans = Min(ans, Min(dis[a][i], dis[b][i]));
a = fa[a][i]; b = fa[b][i];
}
ans = Min(ans, Min(dis[a][0], dis[b][0]));
return ans;
}
}
int main() {
//RS();
n = read(); m = read();
for(rg int i = 1; i <= m; i++) {
int u = read(), v = read(), w = read();
Part1::addedge(u, v, w);
}
Part1::Kruskal();
Part2::init();
int q = read();
while(q--) {
int x = read(), y = read();
writeln(Part2::LCA(x, y));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: