好久不见同志们 现在我更新一发题解
题目
[NOIP2013]货车运输 D1 T3
题目描述
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
下面是一张图
然后是多次询问
My solution
首先,本题需要一个简单的判断,那就是我们需要任意两点间的距离尽可能的大
其次,两点之间的路径只需要一次就可以
这意味着什么呢
我们其实只需要建立一棵树,当然是最大生成树
其次 我们可以找到树上的两个点之间的路径上的最小值
暴力的跑图绝对不是一个好的想法
这意味着我们需要一个lca维护,即分别求出两个点到lca之间的路径的最小值 然后取min即可
本题还有一个附加的问题 就是两点之间的连通性,当然,这个实在是太简单了。。做完kruskral就已经维护出来了,只需要find(x)就行了
那好 我们就说到这里
下面是代码
偶对了 我提前说一下,我已经把我的建图部分改成无向边的了
额 还有
无向边M开二倍
无向边M开二倍
无向边M开二倍
重要的事情说三遍
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 100000+5
#define M 1000000+5
#define inf 0x7fffffff
int f[N],fa[N][17],deep[N],d[N][17],n,m, head[N];
bool vis[N];
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
struct graph
{
int next, to, val;
graph() {}
graph(int _next, int _to, int _val)
: next(_next), to(_to), val(_val) {}
} edge[M];
inline void add(int x, int y, int z)
{
static int cnt = 0;
edge[++cnt] = graph(head[x], y, z);
head[x] = cnt;
swap(x,y);
edge[++cnt] = graph(head[x], y, z);
head[x] = cnt;
}
struct node
{
int from,to,val;
bool operator < (const node &z)const
{
return val>z.val;
}
}a[M];
int find(int x)
{
return f[x]^x?f[x]=find(f[x]):f[x];
}
void dfs(int x)
{
vis[x]=1;
for(int i=1;i<=16;i++)
{
if(deep[x]<(1<<i))break;
fa[x][i]=fa[fa[x][i-1]][i-1];
d[x][i]=min(d[x][i-1],d[fa[x][i-1]][i-1]);
}
for(int i=head[x];i;i=edge[i].next)
{
if(vis[edge[i].to])
continue;
fa[edge[i].to][0]=x;
d[edge[i].to][0]=edge[i].val;
deep[edge[i].to]=deep[x]+1;
dfs(edge[i].to);
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int t=deep[x]-deep[y];
for(int i=0;i<=16;i++)
if((1<<i)&t)
x=fa[x][i];
for(int i=16;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])
{x=fa[x][i];y=fa[y][i];}
}
if(x==y)return x;
return fa[x][0];
}
int ask(int x,int f)
{
int mn=inf;
int t=deep[x]-deep[f];
for(int i=0;i<=16;i++)
{
if(t&(1<<i))
{
mn=min(mn,d[x][i]);
x=fa[x][i];
}
}
return mn;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;++i)
f[i]=i;
for(int i=1;i<=m;++i)
a[i].from=read(),a[i].to=read(),a[i].val=read();
sort(a+1,a+m+1);
memset(d,127/3,sizeof d);
for(int i=1;i<=m;++i)
{
int fx=a[i].from,fy=a[i].to;
fx=find(fx),fy=find(fy);
if(fx^fy)
{
add(fx,fy,a[i].val);f[fx]=fy;
}
}
for(int i=1;i<=n;++i)
if(!vis[i])
dfs(i);
int q=read();
while(q--)
{
int tmp1=read(),tmp2=read();
int fx=find(tmp1),fy=find(tmp2);
if(fx ^ fy)
{
printf("-1\n");
continue;
}
int t=lca(tmp1,tmp2);
printf("%d\n",min(ask(tmp1,t),ask(tmp2,t)) );
}
}