bzoj3322 最大生成树+LCA

题目大意:给个无向图,每条边有个限制,每个点最多能买入和卖出一定黄金;然后按顺序走过n个点,求每个卖出黄金的点最多能卖出多少黄金

一开始有点懵,想着怎么再图上做这个问题,后来知道要先建一棵最大生成树

然后就好做了,做的时候黄金全都拿,不必考虑第一个条件,因为就算花不完也能在之前某个地方少买一点黄金

然后没个询问找前后两个点lca,求路径上的最小边的限制,这样就可以求出卖出多少黄金了

最后要谴责一下非常脑残的数据,有个数据点是两条链,dfs时会爆栈= =,WA了我两天十几次

话说出数据时不应该这样戏弄别人,非常浪费时间和精力又没有意义

一定要手写栈!!

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 #define LL long long
  5 #define INF 21474836470000
  6 using namespace std;
  7 const int maxn = 100010;
  8 struct node{
  9     int from,to,next;
 10     LL cost;
 11 }E[maxn*2],e[maxn*2];
 12 int n,m,q,trade[maxn],fa[maxn][21],Fa[maxn],dep[maxn],head[maxn],tot,logn,order[maxn],scc[maxn],bel,st[maxn*10];
 13 LL pre[maxn][21];
 14
 15 void insert(int u, int v, LL c){
 16     e[++tot].to=v; e[tot].next=head[u]; e[tot].cost=c; head[u]=tot;
 17 }
 18
 19 bool cmp(node a, node b){
 20     return a.cost>b.cost;
 21 }
 22
 23 int find(int x){
 24     return Fa[x]==x?x:Fa[x]=find(Fa[x]);
 25 }
 26
 27 void dfs(int u, int f){
 28     int top=0;
 29     st[++top]=u;
 30     while (top){
 31         u=st[top--]; f=fa[u][0];
 32         dep[u]=dep[f]+1;
 33         for (int i=1; i<=logn; i++) fa[u][i]=fa[fa[u][i-1]][i-1];
 34         for (int i=1; i<=logn; i++) pre[u][i]=min(pre[u][i-1],pre[fa[u][i-1]][i-1]);
 35         for (int i=head[u]; i; i=e[i].next)
 36             if (e[i].to!=f){
 37                 fa[e[i].to][0]=u;
 38                 pre[e[i].to][0]=e[i].cost;
 39                 st[++top]=e[i].to;
 40             }
 41     }
 42 }
 43
 44 LL lca(int u, int v){
 45     LL ret=INF;
 46     if (dep[u]<dep[v]) swap(u,v);
 47     while (dep[u]>dep[v]){
 48         for (int i=logn; i>=0; i--)
 49             if (dep[fa[u][i]]>dep[v]){
 50                 ret=min(ret,pre[u][i]);
 51                 u=fa[u][i];
 52             }
 53         ret=min(ret,pre[u][0]);
 54         u=fa[u][0];
 55     }
 56     if (u==v) return ret;
 57     for (int i=logn; i>=0; i--)
 58         if (fa[u][i]!=fa[v][i]){
 59             ret=min(ret,pre[u][i]);
 60             ret=min(ret,pre[v][i]);
 61             u=fa[u][i]; v=fa[v][i];
 62         }
 63     ret=min(ret,min(pre[v][0],pre[u][0]));
 64     return ret;
 65 }
 66
 67 int main(){
 68     //freopen("motorcycle6.in","r",stdin);
 69     //freopen("test.out","w",stdout);
 70     scanf("%d%d%d", &n, &m, &q);
 71     while ((1<<logn)<n) logn++; tot=1;
 72     memset(pre,50,sizeof(pre));
 73     for (int i=1; i<=n; i++) scanf("%d", &order[i]),Fa[i]=i;//  shunxu
 74     for (int i=1; i<=n; i++) scanf("%d", &trade[i]);//  yaoqiu
 75     for (int i=1; i<=m; i++) scanf("%d%d%lld", &E[i].from, &E[i].to, &E[i].cost);
 76     bel=n;
 77     for (int i=1,x; i<=q; i++) scanf("%d", &x),scc[x]=1,bel=min(bel,x);
 78
 79     sort(E+1,E+1+m,cmp);
 80     int num; if (!q) num=n-1; else num=n-q;
 81     for (int i=1,hehe=0; i<=m; i++){
 82         int x=E[i].from, y=E[i].to;
 83         if (scc[x]) x=bel; if (scc[y]) y=bel;
 84         int fx=find(x), fy=find(y);
 85         if (fx!=fy){
 86             Fa[fx]=fy;
 87             insert(x,y,E[i].cost);
 88             insert(y,x,E[i].cost);
 89             hehe++;
 90             if (hehe==num) break;
 91         }
 92     }
 93     fa[1][0]=0;
 94     dfs(1,0);
 95     LL now=0;
 96     if (trade[order[1]]<0) puts("0"); else now=trade[order[1]];
 97     for (int i=2; i<=n; i++){
 98         int x=order[i-1], y=order[i];
 99         if (scc[x]) x=bel; if (scc[y]) y=bel;
100         now=min(now,lca(x,y));
101         x=order[i-1]; y=order[i];
102         if (trade[y]>0) now+=(LL)trade[y];
103         else{
104             if (now+(LL)trade[y]>0){
105                 now+=(LL)trade[y];
106                 printf("%d\n", -trade[y]);
107             }else{
108                 printf("%lld\n", now);
109                 now=0LL;
110             }
111         }
112         //printf("%lld\n", now);
113     }
114     return 0;
115 }
时间: 2024-09-30 11:04:18

bzoj3322 最大生成树+LCA的相关文章

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

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

luogu 1967 货车运输(最大瓶颈生成树+LCA)

题意:给出一颗n个点的图,q个询问,每次询问u到v的路径中最小的边最大是多少. 图的最大瓶颈生成树有一个性质,对于该图的任意两个点,在树中他们之间路径的最小边最大. 由于这个图不一定联通,于是我们对它的联通块都求一次最大瓶颈生成树. 每次询问就变成了在最大瓶颈生成树上找出u到v路径的最小边. 这个显然可以用LCA维护点到它的2^x祖先之间的边的最小值来解决. # include <cstdio> # include <cstring> # include <cstdlib&g

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

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

ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer (最大生成树+LCA求节点距离)

ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer J. Maze Designer After the long vacation, the maze designer master has to do his job. A tour company gives him a map which is a rectangle. The map consists of N \times MN×M little squares. That is to say, the h

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

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

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

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

uva(11354) 最小瓶颈生成树+LCA

求出最小生成树后lca找最大权即可 #include<cstdio>#include<algorithm>#include<cstring>using namespace std; struct my{   int v;   int next;   int dist;}; struct node{   int x,y;   int dist;   bool operator <(const node& rhs) const {      return di

AC日记——货车运输 codevs

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

8.3-8.7 usaco

vijos1002:青蛙跳河. dp+压缩.距离大于100可以直接%100.然后数据范围小了很多可以dp了. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define clr(x,c) memset(x,c,sizeof(x)