cogs1439 货车运输 LCA

填坑进行时……链接:http://cogs.pro/cogs/problem/problem.php?pid=1439

题意:找出两点间最短路上最大的货运量。

这题正解是网络流图论里的东西。首先我们可以想到一个图里面,边权最大的边一定是在这个图的最大生成树上面的,那么我们就先跑出最大生成树。

跑完后,两点间最大边权就可以直接用$LCA$动态查询即可。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn=10005,maxm=50005;
  7 int fa[maxn];
  8 int getfa(int x)
  9 {
 10     return fa[x]==x?x:fa[x]=getfa(fa[x]);
 11 }
 12 void unionn(int x,int y)
 13 {
 14     x=getfa(x),y=getfa(y);
 15     if(x!=y)fa[y]=x;
 16 }
 17 struct node
 18 {
 19     int from,to,dis,next;
 20 }edge[maxn<<1],tmp[maxm];
 21 int head[maxn],tot;
 22 void addedge(int u,int v,int w)
 23 {
 24     edge[++tot]=(node){u,v,w,head[u]};head[u]=tot;
 25 }
 26 int cmp(const node &a,const node &b)
 27 {
 28     return a.dis>b.dis;
 29 }
 30 int n,m,q;
 31 void Kruskal()
 32 {
 33     for(int i=1;i<=n;i++)fa[i]=i;
 34     int cnt=0;
 35     sort(tmp+1,tmp+m+1,cmp);
 36     for(int i=1;i<=m;i++)
 37     {
 38         int u=tmp[i].from,v=tmp[i].to;
 39         if(getfa(u)!=getfa(v))
 40         {
 41             unionn(u,v);
 42             int w=tmp[i].dis;
 43             addedge(u,v,w);addedge(v,u,w);cnt++;
 44             if(cnt==n-1)break;
 45         }
 46     }
 47 }
 48 int p[maxn][32],dep[maxn],dis[maxn][32];
 49 void dfs(int u,int dept,int fa)
 50 {
 51     dep[u]=dept;
 52     for(int i=head[u];i;i=edge[i].next)
 53     {
 54         int v=edge[i].to;
 55         if(v!=p[u][0])
 56         {
 57             p[v][0]=u;dis[v][0]=edge[i].dis;
 58             dfs(v,dept+1,fa);
 59         }
 60     }
 61 }
 62 void init()
 63 {
 64     for(int i=1;(1<<i)<=n;i++)
 65         for(int j=1;j<=n;j++)p[j][i]=-1,dis[j][i]=2147483647;
 66     for(int j=1;(1<<j)<=n;j++)
 67         for(int i=1;i<=n;i++)
 68             if(p[i][j-1]!=-1)p[i][j]=p[p[i][j-1]][j-1],dis[i][j]=min(dis[i][j-1],dis[p[i][j-1]][j-1]);
 69 }
 70 int lca(int x,int y)
 71 {
 72     int i,res=2147483647;if(dep[x]<dep[y])swap(x,y);
 73     for(i=0;(1<<i)<=dep[x];i++);i--;
 74     for(int j=i;j>=0;j--)
 75         if(dep[x]-(1<<j)>=dep[y])res=min(res,dis[x][j]),x=p[x][j];
 76     if(x!=y)
 77     {
 78         for(int j=i;j>=0;j--)
 79             if(p[x][j]!=p[y][j])res=min(res,min(dis[x][j],dis[y][j])),x=p[x][j],y=p[y][j];
 80         res=min(res,min(dis[x][0],dis[y][0]));
 81     }
 82     return res;
 83 }
 84 int haha()
 85 {
 86     freopen("truck.in","r",stdin);
 87     freopen("truck.out","w",stdout);
 88     scanf("%d%d",&n,&m);
 89     for(int i=1;i<=m;i++)
 90     {
 91         int x,y,z;scanf("%d%d%d",&x,&y,&z);
 92         tmp[i]=(node){x,y,z,0};
 93     }
 94     Kruskal();dfs(1,1,0);init();
 95     scanf("%d",&q);
 96     for(int i=1;i<=q;i++)
 97     {
 98         int x,y;scanf("%d%d",&x,&y);
 99         if(getfa(x)!=getfa(y))puts("-1");
100         else printf("%d\n",lca(x,y));
101     }
102 }
103 int sb=haha();
104 int main(){;}

cogs1439

时间: 2024-11-05 06:24:56

cogs1439 货车运输 LCA的相关文章

LuoguP1967 货车运输 LCA

lca的倍增策略不仅可以维护最近公共祖先,还可以维护其他具有区间可维护性的信息,例如本题中维护的最小限重. 本题调了好久,最后发现原因是数组用混了.以后一定要记准各个数组含义,千万不要混啊... 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 7 using namespace std; 8

倍增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 座城市和

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

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

货车运输

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

AC日记——货车运输 codevs

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

洛谷P1967 [NOIP2013提高组Day1T2]货车运输

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

3287 货车运输 2013年NOIP全国联赛提高组 40 分

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