货车运输(最大生成树+LCA)

题目描述

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入输出格式

输入格式:

输入文件名为 truck.in。

输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道

路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。

接下来一行有一个整数 q,表示有 q 辆货车需要运货。

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。

输出格式:

输出文件名为 truck.out。

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货

车不能到达目的地,输出-1。

输入输出样例

输入样例#1:

4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3

输出样例#1:

3
-1
3

说明

对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000;

对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000;

对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。

题中要求的是图中任意两点间的路径的最小值最大是多少

货车要尽可能的运多的货物,就需要尽可能走权值大的路

所以路径一定在图中的最大生成树上

得到最大生成树后,很容易发现两点间的路径一定经过它们的最近公共祖先,

则可以利用倍增的思想,设p[i][j]表示i节点第2^j个祖先,minx[i][j]表示从i到2^j个祖先的路径最小值

转移方程:p[i][j]=p[p[i][j-1]][j-1]

     minx[i][j]=min(minx[i][j-1],minx[p[i][j-1][j-1])

利用两个数组去求lca和最小路径即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define MAXN 10050
#define MAXE 50050
#define INF 2147483647
using namespace std;
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;
}
int father[MAXN];
int finds(int x)
{
    if(father[x]==x) return x;
    return father[x]=finds(father[x]);
}
struct Line
{
    int u,v,w;
    friend bool operator<(Line a,Line b)
    {
        return a.w>b.w;
    }
} l[MAXE];
struct Edge
{
    int u,v,w;
    int next;
} e[MAXE];
int head[MAXN],cnt=0;
void add(int u,int v,int w)
{
    cnt++;
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt;
}
int n,m,q,deep[MAXN],p[MAXN][20],minx[MAXN][20],deps;
void kruskal()
{
    for(int i=1; i<=n; i++)father[i]=i;
    sort(l+1,l+m+1);
    for(int i=1; i<=m; i++)
    {
        int u=finds(l[i].u);
        int v=finds(l[i].v);
        if(u!=v)
        {
            father[v]=u;
            add(l[i].u,l[i].v,l[i].w);
            add(l[i].v,l[i].u,l[i].w);
        }
    }
}
void dfs(int u)
{
    for(int i=head[u]; i!=0; i=e[i].next)
        if(!deep[e[i].v])
        {
            deep[e[i].v]=deep[u]+1;
            p[e[i].v][0]=u;
            minx[e[i].v][0]=e[i].w;
            dfs(e[i].v);
        }
}
inline int lca(int x, int y)
{
    int ans=INF;
    if(deep[x]>deep[y]) swap(x, y);
    for(int i=15; i>=0; i--)
        if(deep[p[y][i]]>=deep[x])
        {
            ans=min(ans,minx[y][i]);
            y=p[y][i];
        }
    if(x==y) return ans;
    for(int i=15; i>=0; i--)
        if(p[x][i]!=p[y][i])
        {
            ans = min(ans, min(minx[x][i], minx[y][i]));
            x=p[x][i];
            y=p[y][i];
        }
    return min(ans, min(minx[x][0], minx[y][0]));
}
int main()
{
    n=read(),m=read();
    for(int i=1; i<=m; i++)
        l[i].u=read(),l[i].v=read(),l[i].w=read();
    kruskal();
    deep[1]=1;
    dfs(1);
    for(int j=1; j<=15; j++)
        for(int i=1; i<=n; i++)
        {
            p[i][j]=p[p[i][j-1]][j-1];
            minx[i][j]=min(minx[i][j-1],minx[p[i][j-1]][j-1]);
        }
    q=read();
    for(int i=1; i<=q; i++)
    {
        int u=read(),v=read();
        if(finds(u)!=finds(v))
        {
            printf("-1\n");
            continue;
        }
        printf("%d\n",lca(u,v));
    }
}
时间: 2024-11-03 22:33:48

货车运输(最大生成树+LCA)的相关文章

货车运输(最大生成树,LCA)

洛咕 题意:A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有q辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物? 分析:显然限重就是边权.构建出图的最大生成树,然后树上每个节点dfs预处理出f[v][0]和dis[v][0],分别表示节点v的\(2^0\)级祖先(即父节点)是谁以及它到父节点的距离;然后对于每一个询问,利用倍增思想在树上LCA. #include<bits/stdc++.h> using nam

luogu1967[NOIP2013D1T3] 货车运输 (最大生成树+LCA)

题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z

NOIP2013 货车运输(最大生成树+LCA)

模拟考试的时候暴搜,结果写丑了,分都不分 下来啃了一下题解,发现要用到一个叫做倍增的东西,还没有学过.但是老师说的,没有那个东西,写暴力也有30~40分... 我觉得最大生成树还是很好理解的,因为我们要求的是图中任意两个点之间的路径上,使得边权的最小值尽量大.因此首先求最大生成树. 当我们得到最大生成树后,要求两个点之间边权最小值,我们可以首先找到他们的公共祖先.这里有一篇写得很详细的代码,并且注明了各种写法的得分http://blog.csdn.net/gengmingrui/article/

$Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$

$Luogu$ $Sol$ 首先当然是构建一棵最大生成树,然后对于一辆货车的起点和终点倍增跑$lca$更新答案就好.记得预处理倍增的时候不仅要处理走了$2^i$步后是那个点,还有这中间经过的路径权值的最小值以便之后统计答案. 再一看发现这题并没说给的图是联通的,也就是说跑了最大生成树之后可能有若干棵树.所以构树的时候要注意不能随便选一个点构完就不管了,要对每一个联通块都构一次.其他的地方似乎没有因为它有多棵树而有什么不同,只是询问的时候看下是不是一个联通块里的就好. $Code$ #includ

luogu P1967 货车运输 最大生成树 倍增LCA

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 struct edg 7 { 8 int x,y,w; 9 friend bool operator < (edg x,edg y) 10 { 11 return x.w > y.w; 12 } 13 } vec[110000]; 1

洛谷 P1967 货车运输 Label: 倍增LCA &amp;&amp; 最小瓶颈路

题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z

【luogu1967】【noip2013】 货车运输 [生成树kruskal LCA ]

P1967 货车运输最大生成树+倍增算路径最小值 最大生成树就是kruskal时将边改为降序 然后就和普通kruskal一样 然后就是用的LCA倍增模板中说的其它骚操作一样 可以在预处理的时候还可以顺便记录下这段路径的权值最大值 最小值或者权值和之类的信息,这样就可以在O(logn)的时间内求出树上两点间路径权值的最大值.最小值还有权值和 #include<iostream> #include<cstdio> #include<queue> #include<cs

倍增LCA NOIP2013 货车运输

货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条

poj1330|bzoj3732|noip2013 货车运输 kruskal+倍增lca

学了一早上倍增,感觉lca还是tarjan好写. poj1330 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #include <algorithm> 5 #define DEG 20//2^20 6 #define maxn 10010 7 using namespace std; 8 struct node 9 { 10 int v, next; 11 }a[maxn*2

C++之路进阶——LCA(货车运输)

3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和