[APIO2013]道路费用
题目描述
幸福国度可以用 N 个城镇(用 1 到 N 编号)构成的集合来描述,这些城镇 最开始由 M 条双向道路(用 1 到 M 编号)连接。城镇 1 是中央城镇。保证一个 人从城镇 1 出发,经过这些道路,可以到达其他的任何一个城市。这些道路都是 收费道路,道路 i 的使用者必须向道路的主人支付 ci分钱的费用。已知所有的这 些ci是互不相等的。最近有K条新道路建成,这些道路都属于亿万富豪Mr. Greedy。 Mr. Greedy 可以决定每条新道路的费用(费用可以相同),并且他必须在明天宣 布这些费用。
两周以后,幸福国度将举办一个盛况空前的嘉年华!大量的参与者将沿着这 些道路游行并前往中央城镇。共计 pj个参与者将从城镇 j 出发前往中央城镇。这 些人只会沿着一个选出的道路集合前行,并且这些选出的道路将在这件事的前一 天公布。根据一个古老的习俗,这些道路将由幸福国度中最有钱的人选出,也就 是 Mr. Greedy。同样根据这个习俗,Mr. Greedy 选出的这个道路集合必须使所有 选出道路的费用之和最小,并且仍要保证任何人可以从城镇 j 前往城镇 1(因此, 这些选出的道路来自将费用作为相应边边权的“最小生成树”)。如果有多个这样 的道路集合,Mr. Greedy 可以选其中的任何一个,只要满足费用和是最小的。
Mr. Greedy 很明确地知道,他从 K 条新道路中获得的收入不只是与费用有 关。一条道路的收入等于所有经过这条路的人的花费之和。更准确地讲,如果 p 个人经过道路 i,道路 i 产生的收入为 ci p 的积。注意 Mr. Greedy 只能从新道路 收取费用,因为原来的道路都不属于他。
Mr. Greedy 有一个阴谋。他计划通过操纵费用和道路的选择来最大化他的收 入。他希望指定每条新道路的费用(将在明天公布),并且选择嘉年华用的道路 (将在嘉年华的前一天公布),使得他在 K 条新道路的收入最大。注意 Mr. Greedy 仍然需要遵循选出花费之和最小的道路集合的习俗。
你是一个记者,你想揭露他的计划。为了做成这件事,你必须先写一个程序 来确定 Mr. Greedy 可以通过他的阴谋获取多少收入。
题解
我们需要让这k条边的代价最大。
看到k很小,可以想到枚举每条边的选择情况,但如果直接每次跑一遍最小生成树会使复杂度变得很高。
首先我们把这\(k\)条边先加进去,然后再对其他边跑最小生成树,那么此时加进去的边一定是必须在最后的生成树里的。
那么我们把这些边提前加进去,这样会形成\(k+1\)个联通块,我们把这些联通块看做点,那么点数的级别就变成了\(O(K)\)的。
然后我们还发现有些边是没用的,我们先把联通块缩点,然后用\(kruskal\)尝试填加其他边,那么我们只会填加\(k\)条边,可以发现,此时还没有添加进去的边是没有用的,这些边就是可能会加进去的边,这样边数也是\(O(K)\)的了。
对于新边的权值的设定,就是所有跨过它的边的权值最小值。
然后这道题就变成大模拟了。。
代码
#include<bits/stdc++.h>
#define N 100009
#define M 300009
#define K 22
#define inf 2e9
using namespace std;
typedef long long ll;
int f[N],n,m,k,l[N],r[N],dep[N],be[N],tot,num[N],tong[N],ma[K],mx[N],ji[K];
ll size[N],w[N],sum[N],ans;
bool vis[N];
int head[K],tott;
struct edge{
int n,to,l;
}e[K<<1];
inline void add(int u,int v,int l){
e[++tott].n=head[u];e[tott].to=v;head[u]=tott;e[tott].l=l;
}
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
int find(int x){return f[x]=f[x]==x?x:find(f[x]);}
inline int zh(int x){return tong[be[x]];}
struct node{
int u,v,w;
inline bool operator <(const node &b)const{return w<b.w;}
}b[M];
ll dfs(int u,int fa){
size[u]=sum[u];
ll ans=0;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;
ans+=dfs(v,u);
size[u]+=size[v];
if(e[i].l)ans+=size[v]*mx[v];
}
return ans;
}
void dfs0(int u,int fa){
if(!fa)f[u]=u;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;f[v]=u;dep[v]=dep[u]+1;
dfs0(v,u);
}
}
int main(){
n=rd();m=rd();k=rd();
for(int i=1;i<=m;++i){
b[i].u=rd();b[i].v=rd();b[i].w=rd();
}
sort(b+1,b+m+1);
for(int i=1;i<=n;++i)f[i]=i;
for(int i=1;i<=k;++i){
l[i]=rd();r[i]=rd();
int xx=find(l[i]),yy=find(r[i]);
if(xx!=yy)f[xx]=yy;
}
for(int i=1;i<=n;++i)w[i]=rd();
for(int i=1;i<=m;++i){
int xx=find(b[i].u),yy=find(b[i].v);
if(xx!=yy)f[xx]=yy,num[++num[0]]=i,vis[i]=1;
}
for(int i=1;i<=n;++i)f[i]=i;
for(int i=1;i<=num[0];++i){
int xx=find(b[num[i]].u),yy=find(b[num[i]].v);
if(xx!=yy)f[xx]=yy;
}
for(int i=1;i<=n;++i){
be[i]=find(i);
if(!tong[be[i]])tong[be[i]]=++tot;
sum[tong[be[i]]]+=w[i];
}
for(int i=1;i<=m;++i){
int xx=find(b[i].u),yy=find(b[i].v);
if(xx!=yy){
f[xx]=yy;
ma[++ma[0]]=i;
}
}
for(int i=0;i<(1<<k);++i){
tott=0;ji[0]=0;
memset(head,0,sizeof(head));
for(int j=1;j<=tot;++j){
f[j]=j,dep[j]=0;mx[j]=inf;
}
for(int j=1;j<=k;++j)if(i&(1<<j-1)){
int xx=find(zh(l[j])),yy=find(zh(r[j]));
if(xx!=yy){
f[xx]=yy;
int x=zh(l[j]),y=zh(r[j]);
add(x,y,1);add(y,x,1);
}
}
for(int j=1;j<=ma[0];++j){
int xx=find(zh(b[ma[j]].u)),yy=find(zh(b[ma[j]].v));
if(xx!=yy){
f[xx]=yy;
int x=zh(b[ma[j]].u),y=zh(b[ma[j]].v);
add(x,y,0);add(y,x,0);
}
else{
ji[++ji[0]]=ma[j];
}
}
dfs0(zh(1),0);
for(int j=1;j<=ji[0];++j){
int xx=zh(b[ji[j]].u),yy=zh(b[ji[j]].v);
if(dep[xx]<dep[yy])swap(xx,yy);
while(dep[xx]>dep[yy])mx[xx]=min(mx[xx],b[ji[j]].w),xx=f[xx];
while(xx!=yy){
mx[xx]=min(mx[xx],b[ji[j]].w);
mx[yy]=min(mx[yy],b[ji[j]].w);
xx=f[xx];yy=f[yy];
}
}
ans=max(ans,dfs(zh(1),0));
}
printf("%lld\n",ans);
return 0;
}
[APIO2013]道路费用的更多相关文章
- [BZOJ3206][APIO2013]道路费用(最小生成树)
3206: [Apio2013]道路费用 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 568 Solved: 266[Submit][Status ...
- [Bzoj3206][Apio2013]道路费用(kruscal)(缩点)
3206: [Apio2013]道路费用 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 536 Solved: 252[Submit][Status ...
- 洛谷P3639 [APIO2013] 道路费用 [生成树的特殊算法]
题目传送门 道路费用 格式难调,题面就不放了. 分析: 这是一道要细(yan)心(jing)的生成树的好(gui)题. 首先我们看到$k$的范围非常小,那么我们就可以直接$2^k$枚举每一条加边是否选 ...
- 题解 [APIO2013]道路费用
link Description 幸福国度可以用 N 个城镇(用 1 到 N 编号)构成的集合来描述,这些城镇 最开始由 M 条双向道路(用 1 到 M 编号)连接.城镇 1 是中央城镇.保证一个 人 ...
- BZOJ3206 [Apio2013]道路费用
首先我们强制要求几条待定价的边在MST中,建出MST 我们发现这个MST中原来的边是一定要被选上的,所以可以把点缩起来,搞成一棵只有$K$个点的树 然后$2^K$枚举每条边在不在最终的MST中,让在最 ...
- bzoj 3206: [Apio2013]道路费用【最小生成树+并查集】
参考:http://hzwer.com/6888.html 把k条道路权值设为0,和其他边一起跑MST,然后把此时选中的其他边设为必选,在新图中加上必选变缩成k个点,把所有边重标号,枚举k跳边的选取情 ...
- 题解 洛谷 P3639 【[APIO2013]道路费用 】
不难想到可以\(2^k\)去枚举\(k\)条新边的选择方案,然后加入原图中的边来使图连通,用当前方案的收益去更新答案,但是这样复杂度过不去. 可以先把\(k\)条新边都连上,然后再加入边权从小到大排序 ...
- [APIO2013]
A.机器人 题目大意:给定一个n*m的地图,有一些障碍物和k个机器人,你每次可以选择一个机器人往任意一个方向推,遇到转向器会转向,两个编号相邻的机器人可以合并,求最少推多少次可以全部合并. $n,m\ ...
- PKUSC2018训练日程(4.18~5.30)
(总计:共66题) 4.18~4.25:19题 4.26~5.2:17题 5.3~5.9: 6题 5.10~5.16: 6题 5.17~5.23: 9题 5.24~5.30: 9题 4.18 [BZO ...
随机推荐
- [USACO 2008 Jan. Silver]架设电话线 —— 最短路+二分
一道图论的最短路题.一开始连最短路都没想到,可能是做的题太少了吧,完全没有思路. 题目大意: FJ的农场周围分布着N根电话线杆,任意两根电话线杆间都没有电话线相连.一共P对电话线杆间可以拉电话线,第i ...
- 20191023 XXL-JOB
概述 XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.现已开放源代码并接入多家公司线上产品线,开箱即用. 文档地址: 官方文档 文档写的很详细,参考着 ...
- CentOS7 redhat7 linux系统1分钟安装Zabbix web 监控 服务器
一.准备工作OS:centos7.4Zabbix version:3.4.6(2018/1/15日上线的新版本)Database:MariaDB关闭防火墙:systemctl stop firewal ...
- 关于toString()和valueOf()以及Object.prototype.toString.call()的结合理解
一.先说说String(): String()是全局函数,把对象的值转换为字符串. 语法:String(obj); 任何值(对象)都有String()方法,执行过程是这样的:首先,如果该对象上有toS ...
- Codeforces 691E题解 DP+矩阵快速幂
题面 传送门:http://codeforces.com/problemset/problem/691/E E. Xor-sequences time limit per test3 seconds ...
- vue 跳转页面返回时tab状态有误的解决办法
一.前言 最近在做新vue项目的时候遇到了一个问题,就是tab间的切换没有问题,当跳转到其他页面时,且这个页面并非子路由,再用浏览器的返回按钮返回首页时,tab的active始终指向默认的第一个选项. ...
- python学习第四十二天列表生成式用法及作用
在操作列表或者元组的时候,对一系列的数据进行算法,比较整个数据加1,或翻倍,用传统的算法就很繁琐,列表给我们提供简便的方法 a=[i*i for i in rang(10)] a=[1,4,9,16, ...
- Vue组件通信方式(一)
组件与组件的关系,通常有父子关系,兄弟关系以及隔代关系. 针对不同的场景,如何选用适合的通信方式呢? (一) props/$emit parentComponent ==> childCompo ...
- 最长回文子序列/最长回文子串(DP,马拉车)
字符子串和字符子序列的区别 字符字串指的是字符串中连续的n个字符:如palindrome中,pa,alind,drome等都属于它的字串 而字符子序列指的是字符串中不一定连续但先后顺序一致的n个字符: ...
- 处理键盘事件 禁止后退键(Backspace)密码或单行、多行文本框除外
//处理键盘事件 禁止后退键(Backspace)密码或单行.多行文本框除外 function forbidBackSpace(e) { var ev = e || window.event; //获 ...