Codeforces GYM 100876 J - Buying roads 题解

才不是因为有了图床来测试一下呢,哼(

题意

给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得得到的子图联通并且总代价最小,输出最小总代价和一种方案。

虽然题目里描述的很冗长,但其实这个图有一些性质:它最初是一条链/一个环,然后再有一些结点直接连到这些在链上/环上的结点。、

下图就是一个(就是样例):

做法

首先我们可以简单的查看点的度数来找到链/环上的点,和连接它们的边。

然后我们可以通过对链的头和尾添加一条权值大到足够保证不会选到它的边,把链变成环(样例被更改的样子):

我们可以枚举选择的是环上的相连的一条链,选择这些环上的边的同时,也贪心地从小到大选择挂在环上(类似于连接\(8\)和\(9\))的边。

这里可以枚举链的起点,在不断扩展这条链的右端点(并强制选取达到的它的边)的同时,维护一个堆,堆里存放的是选择的链上挂的边的权值最大值,每次添加时去查看添加的边的权值是否小于这个最大值,然后更新这个堆即可。

需要注意有选择整个环而非一部分的链的方案。

程序

这里把计算答案和构造方案分开了,实现起来可能比较方便。

#include<bits/stdc++.h>
using namespace std; typedef long long ll; int n,m,K;
vector<pair<int,int>> g[2005];
vector<int> hang[2005];
vector<int> node,edge;
ll w[2005],ans=1e18; void get_imp(const int &x,const int &p,const int &head){
node.emplace_back(x);
for(pair<int,int> &e:g[x]){
if(e.first!=p&&g[e.first].size()>1){
edge.emplace_back(e.second);
if(e.first!=head)get_imp(e.first,x,head);
return;
}
}
} void get_ans_val(){
priority_queue<int> heap;
ll cur;
for(int i=0;i<node.size();i++){
while(!heap.empty())heap.pop();
cur=0;
for(int jj=i;jj<i+K&&jj<i+node.size();jj++){
int j=jj%node.size();
for(int k=0;k<hang[node[j]].size();k++){
if(heap.size()+jj-i<K){
heap.emplace(w[hang[node[j]][k]]);
cur+=w[hang[node[j]][k]];
}else if(heap.top()>w[hang[node[j]][k]]){
cur-=heap.top();
heap.pop();
cur+=w[hang[node[j]][k]];
heap.emplace(w[hang[node[j]][k]]);
}else break;
}
if(heap.size()+jj-i==K){
ans=min(ans,cur);
cur-=heap.top();
heap.pop();
}
cur+=w[edge[j]];
}
ans=min(ans,cur);
}
} void construct(set<int> &use){
priority_queue<pair<int,int>> heap;
ll cur;
for(int i=0;i<node.size();i++){
while(!heap.empty())heap.pop();
cur=0;
use.clear();
for(int jj=i;jj<i+K&&jj<i+node.size();jj++){
int j=jj%node.size();
for(int k=0;k<hang[node[j]].size();k++){
if(heap.size()+jj-i<K){
heap.emplace(w[hang[node[j]][k]],hang[node[j]][k]);
use.insert(hang[node[j]][k]);
cur+=w[hang[node[j]][k]];
}else if(heap.top().first>w[hang[node[j]][k]]){
cur-=heap.top().first;
use.erase(heap.top().second);
heap.pop();
cur+=w[hang[node[j]][k]];
heap.emplace(w[hang[node[j]][k]],hang[node[j]][k]);
use.insert(hang[node[j]][k]);
}else break;
}
if(heap.size()+jj-i==K){
if(cur==ans)return;
cur-=heap.top().first;
use.erase(heap.top().second);
heap.pop();
}
cur+=w[edge[j]];
use.insert(edge[j]);
}
if(cur==ans)return;
}
} int main(){ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0); if(fopen("roads.in","r")){
freopen("roads.in","r",stdin);
freopen("roads.out","w",stdout);
} cin>>n>>m>>K;
for(int i=1;i<=m;i++){
static int u,v,W;
cin>>u>>v>>W;
g[u].emplace_back(v,i);
g[v].emplace_back(u,i);
w[i]=W;
}
for(int i=1;i<=n;i++){
if(g[i].size()==1)hang[g[i].front().first].emplace_back(g[i].front().second);
else if(node.empty()){
int cnt=0;
for(pair<int,int> &e:g[i])cnt+=g[e.first].size()>1;
if(cnt==1)get_imp(i,-1,i);
}
}
if(node.empty())for(int i=1;i<=n;i++){
if(g[i].size()>1){
get_imp(i,-1,i);
break;
}
}
if(edge.size()+1==node.size()){
edge.emplace_back(++m);
w[m]=1e15;
}
for(int i=1;i<=n;i++)sort(hang[i].begin(),hang[i].end(),[](const int &a,const int &b){
return w[a]<w[b];
});
get_ans_val();
cout<<ans<<'\n';
set<int> s;
construct(s);
for(const int &x:s)cout<<x<<'\n'; return 0;
}

Codeforces GYM 100876 J - Buying roads 题解的更多相关文章

  1. Codeforces gym 101343 J.Husam and the Broken Present 2【状压dp】

     2017 JUST Programming Contest 2.0 题目链接:Codeforces gym 101343 J.Husam and the Broken Present 2 J. Hu ...

  2. codeforces Gym 100187J J. Deck Shuffling dfs

    J. Deck Shuffling Time Limit: 2   Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/pro ...

  3. codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

    题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” ...

  4. codeforces Gym 100500 J. Bye Bye Russia

    Problem J. Bye Bye RussiaTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/1005 ...

  5. codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点

    J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Des ...

  6. Codeforces Gym 100338C C - Important Roads tarjan

    C - Important RoadsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contes ...

  7. codeforces gym 100947 J. Killing everything dp+二分

    J. Killing everything time limit per test 4 seconds memory limit per test 64 megabytes input standar ...

  8. codeforces gym 100357 J (网络流)

    题目大意 有n种物品,m种建筑,p个人. n,m,p∈[1,20] 每种建筑需要若干个若干种物品来建造.每个人打算建造一种建筑,拥有一些物品. 主角需要通过交易来建造自己的建筑,交易的前提是对方用多余 ...

  9. Codeforces Gym 100114 J. Computer Network

    Description 给出一个图,求添加一条边使得添加后的图的桥(割边)最少. Sol Tarjan. 一遍Tarjan求割边. 我们发现连接的两个点一定是这两个点之间的路径上的桥最多,然后就可以贪 ...

随机推荐

  1. [luogu3292]幸运数字

    考虑点分治,将询问离线后计算重心到每一个点的线性基,然后再询问重心到每一个点的线性基,时间复杂度为$o(3600q)$,可以过(然而太菜的我写了倍增维护线性基,震惊于倍增和线性基常数之小) 1 #in ...

  2. 【Sass/SCSS】我花4小时整理了的Sass的函数

    [Sass/SCSS]我花4小时整理了的Sass的函数 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 Sass 定义了各 ...

  3. java实现自动化发布平台核心代码

    1.搭建jenkins环境 (1)jenkins官网下载jenkins.war包 (2)将该war包放入到tomcat的webapp的目录下(前提条件需要配置tomcat的环境,详情请自行百度) (3 ...

  4. Pólya 定理学习笔记

    在介绍\(Polya\) 定理前,先来介绍一下群论(大概了解一下就好): 群是满足下列要求的集合: 封闭性:即有一个操作使对于这个集合中每个元素操作完都使这个集合中的元素 结合律:即对于上面那个操作有 ...

  5. Codeforces 1208F - Bits And Pieces(高维前缀和)

    题面传送门 题意:求 \(\max\limits_{i<j<k}a_i|(a_j\&a_k)\). \(1\leq n \leq 10^6,1\leq a_i\leq 2\time ...

  6. 有限元边界 Dirichlet 条件处理

    参考自百度文档,这里只考虑 Dirichlet 边界条件情况. 有限元法基本方法就是是构造线性方程组 \[\begin{equation} Au = f \end{equation}\] 进行求解.其 ...

  7. RepeatModeler安装及使用

    如果进行重复序列的预测,则使用RepeatModeler,可自身比对进行查找 安装 (1)下载地址:http://www.repeatmasker.org/RepeatModeler/ (2)Repe ...

  8. 执行脚本source 和 . 和sh 的区别是什么

    "source"和"."的功能是一样的,可以调用脚本,并将脚本里的函数也传递到当前的脚本或者解释器中,即不会开启新的bash而是在当前bash中运行. &quo ...

  9. Linux服务器I/O性能分析-1

    一.IOSTAT误区 1.1 误区-svctm Linux上的svctm是重要的I/O指标(I/O平均服务时间-单位毫秒),这个值直接反映了硬件的性能(I/O请求从SCSI层发出--->I/O完 ...

  10. Bebug与Release版本

    如果调试过程无调试信息,检查编译选项是否切换到了release下 比如Cfree5等编译器 ms为了方便调试才诞生了DEBUG版. 这也导致了MFC有两个功能一至但版本不同的类库,一个为DEBUG版, ...