CodeForces 125E MST Company
The MST (Meaningless State Team) company won another tender for an important state reform in Berland.
There are n cities in Berland, some pairs of the cities are connected by roads. Each road has its price. One can move along any road in any direction. The MST team should carry out the repair works on some set of roads such that one can get from any city to any other one moving only along the repaired roads. Moreover, this set should contain exactly k capital roads (that is, the roads that start or finish in the capital). The number of the capital is 1.
As the budget has already been approved, the MST Company will profit by finding the set with minimum lengths of roads.
The first input line contains three integers n, m, k (1 ≤ n ≤ 5000;0 ≤ m ≤ 105;0 ≤ k < 5000), where n is the number of cities in the country, m is the number of roads in the country, k is the number of capital roads in the required set. Then m lines enumerate the roads in question. Each road is specified by three numbers ai, bi, wi (1 ≤ ai, bi ≤ n; 1 ≤ w ≤ 105), where ai, bi are the numbers of cities linked by a road and wi is its length.
Between each pair of cities no more than one road exists. There are no roads that start and finish in one city. The capital's number is 1.
In the first line print the number of roads in the required set. The second line should contain the numbers of roads included in the sought set. If the sought set does not exist, print -1.
4 5 2
1 2 1
2 3 1
3 4 1
1 3 3
1 4 2
3
1 5 2
代码基本靠抄,自己吃枣药丸。
传说这题做法主要有两种:
一:
先做出不含1点的最小生成树。
如果将连接到1的边加进生成树会形成环的话,就在环中找到最长的一条边删掉。
↑计算加某条边会使答案增加的量,然后从连接到1的边里选出增量最小的边进行上述操作,重复k次得到最终结果。
↑写了好久好久都写不出,怒砸键盘,换第二种写法。结果第二天看到隔壁yhx大神分分钟按上述算法切题……
害怕。
附传送门:http://blog.csdn.net/sdfzyhx/article/details/53500851
还有自己写了半天调不对的代码,姑且先存着:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define LL unsigned long long
using namespace std;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct edge{int x,y;int v;int id;}e[mxn*];
int cmp(const edge a,const edge b){return a.v<b.v;}
struct sdd{int v,nxt,dis,id;}eg[mxn<<];
int hd[mxn],egct=;
void add_edge(int u,int v,int dis,int id){
eg[++egct].v=v;eg[egct].nxt=hd[u];eg[egct].dis=dis;eg[egct].id=id;hd[u]=egct;return;
}
int n,m,k;
int ans=;
int st[mxn],top;
int fir[mxn*],mct=;//存所有与1相连的边
//
int fa[mxn];
int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]);}
int add[mxn];
bool del[mxn];
bool intree[mxn];
inline void init(int x){for(register int i=;i<=x;i++)fa[i]=i;}//并查集初始化
void PD(){
int cnt=;
for(int i=;i<=n;i++){if(find(i)==i)cnt++;}
if(cnt>k){printf("-1\n");exit();}//联通块数多于可加边数,无解
return;
}
int mx[mxn],m_id[mxn];
void DFS(int u,int f){
for(int i=hd[u];i;i=eg[i].nxt){
int v=eg[i].v;
if(v==f || !intree[eg[i].id])continue;
if(u==){mx[v]=1e9;m_id[v]=;}
bool flag=;
if(eg[i].dis<mx[v]){
mx[v]=eg[i].dis;
m_id[v]=eg[i].id;
flag=;
}
if(mx[v]>mx[u]){
mx[v]=mx[u];
m_id[v]=m_id[u];
flag=;
}
if(flag)DFS(v,u);
}
return;
}
int belone[mxn];
void solve(){
top=;
int i,j,u,v;
int cnt=;
//
sort(e+,e+m+,cmp);
init(n);
for(i=;i<=m;i++){
if(e[i].x== || e[i].y==)continue;
u=find(e[i].x);v=find(e[i].y);
if(u!=v){
fa[u]=v;
ans+=e[i].v;
intree[e[i].id]=;//记录是否在树中
add_edge(e[i].x,e[i].y,e[i].v,e[i].id);
add_edge(e[i].y,e[i].x,e[i].v,e[i].id);
cnt++;
}
if(cnt==n-)break;//除1以外都连通时,退出
}
//kruskal处理出除点1以外的生成树
PD();
//
init(n);
for(i=;i<=n;i++){belone[i]=find(i);}
for(i=;i<=m;i++)//找出待加的1边
if(e[i].x== || e[i].y==){
if(e[i].y==)swap(e[i].x,e[i].y);
fir[++mct]=i;
}
memset(mx,0x3f,sizeof mx);
for(i=;i<=mct;i++){
if(e[fir[i]].v<mx[belone[e[fir[i]].y]]){
mx[belone[e[fir[i]].y]]=e[fir[i]].v;
m_id[belone[i]]=fir[i];
}
}
cnt=;
for(i=;i<=n;i++){//加入和点1相连的边使图连通
if(belone[i]!=i)continue;
intree[e[m_id[i]].id]=;
cnt++;
ans+=e[m_id[i]].v;
add_edge(e[m_id[i]].x,e[m_id[i]].y,e[m_id[i]].v,e[m_id[i]].id);
add_edge(e[m_id[i]].y,e[m_id[i]].x,e[m_id[i]].v,e[m_id[i]].id);
}
for(i=cnt+;i<=k;i++){
DFS(,);
int tmp1=1e9,tmp2,tmp3;
for(j=;j<=mct;j++){//尝试替换1边
int to=e[fir[j]].y;
if(e[fir[j]].v-mx[to]<tmp1){
tmp1=e[fir[j]].v+mx[to];
tmp2=fir[j];
tmp3=m_id[to];
}
ans+=tmp1;
intree[e[tmp2].id]=;//加入1边
intree[e[tmp3].id]=;//删除一条边
}
}
return;
}
int main()
{
int i,j;
n=read();m=read();k=read();
for(i=;i<=m;i++){
e[i].x=read();e[i].y=read();
e[i].v=read();e[i].id=i;
fa[find(e[i].x)]=fa[find(e[i].y)];
}
for(i=;i<n;i++)if(find(i)!=find(i+)){
printf("-1\n");return ;
}//无法连通,无解
solve();
printf("%d\n",ans);
return ;
}
二:
加边的增量具有单调性。二分可能的增量,以此为基准将与1相连的边排序并加入生成树,看何时能正好加入k条,就是答案了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define LL unsigned long long
using namespace std;
const double eps=1e-;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct edge{
int x,y;
int v;
int id;
}e[mxn*];
double mid;
int cmp(const edge a,const edge b){
return (double)(a.x==)*mid+(double)a.v < (double)(b.x==)*mid+(double)b.v;
}
int n,m,k;
int tot=;
//
int fa[mxn];
int find(int x){
if(fa[x]==x)return fa[x];
return fa[x]=find(fa[x]);
}
int ans[mxn],mct=;
void solve(bool flag){
for(int i=;i<=n;i++)fa[i]=i;
sort(e+,e+m+,cmp);
tot=;mct=;
for(int i=;i<=m;i++){
int u=find(e[i].x),v=find(e[i].y);
if(u!=v && (tot+(e[i].x==)<=k || flag)){
fa[u]=v;
ans[++mct]=e[i].id;
if(e[i].x==)tot++;
}
}
}
int main()
{
n=read();m=read();k=read();
int i,j;
int dg1=;
for(i=;i<=m;i++){
e[i].x=read();e[i].y=read();e[i].v=read();e[i].id=i;
if(e[i].x>e[i].y)swap(e[i].x,e[i].y);
if(e[i].x==)dg1++;
}
if(dg1<k || (n> && k==)){printf("-1\n");return ;}//不能满足k要求
mid=;
solve();
if(mct<n-){printf("-1\n");return ;}//不能生成树
double l=-1e5,r=1e5;
while(l+eps<r && tot!=k){
mid=(l+r)/;
solve();
if(tot<k)r=mid;
else l=mid;
}
if(tot!=k)mid=(l+r)/;
solve();
printf("%d\n",mct);
for(i=;i<=mct;i++)printf("%d ",ans[i]);
return ;
}
CodeForces 125E MST Company的更多相关文章
- CODEFORCES 125E MST Company 巧用Kruskal算法
题意:给定一个带权边无向图,求最小生成树,且满足第一个节点的度为固定的k 无解则输出-1 数据规模: 节点数n和限制k<=5000 边数m<=10^5 时限8sec 思路: 首先时限比较宽 ...
- 【CF125E】MST Company(凸优化,最小生成树)
[CF125E]MST Company(凸优化,最小生成树) 题面 洛谷 CF 题解 第一眼看见就给人丽洁姐那道\(tree\)一样的感觉. 那么二分一个权值,加给所有有一个端点是\(1\)的边, 然 ...
- Codeforces 1108F MST Unification MST + LCA
Codeforces 1108F MST + LCA F. MST Unification Description: You are given an undirected weighted conn ...
- luogu CF125E MST Company wqs二分 构造
LINK:CF125E MST Company 难点在于构造 前面说到了求最小值 可以二分出斜率k然后进行\(Kruskal\) 然后可以得到最小值.\(mx\)为值域. 得到最小值之后还有一个构造问 ...
- Codeforces 556D Restructuring Company
传送门 D. Restructuring Company time limit per test 2 seconds memory limit per test 256 megabytes input ...
- [刷题]Codeforces 794C - Naming Company
http://codeforces.com/contest/794/problem/C Description Oleg the client and Igor the analyst are goo ...
- Codeforces 1108F MST Unification(最小生成树性质)
题目链接:MST Unification 题意:给定一张连通的无向带权图.存在给边权加一的操作,求最少操作数,使得最小生成树唯一. 题解:最小生成树在算法导论中有这个性质: 把一个连通无向图的生成树边 ...
- Codeforces 1062 E - Company
E - Company 思路: 首先,求出每个点的dfs序 然后求一些点的公共lca, 就是求lca(u, v), 其中u是dfs序最大的点, v是dfs序最小的大点 证明: 假设o是这些点的公共lc ...
- [CF125E]MST Company
codeforces description 给出一张\(n\)点\(m\)条边的无向图,求一棵满足\(1\)号点度数恰好为\(k\)的最小生成树,并输出方案. \(1\le k\le n\le500 ...
随机推荐
- ViewModelBase && ObservableObject
ViewModelBase && ObservableObject 在Mvvm中,ViewModel和Model都需要具有通知界面更新数据的能力,这都要借助于WPF中的 INotify ...
- Linux学期总结
学习笔记链接 第一次 http://www.cnblogs.com/Spr1ngxx/p/4823573.html 第二次 http://www.cnblogs.com/Spr1ngxx/p/4842 ...
- .NET MVC AjaxHelper
我们首先必须开启 非入侵式 Ajax:导入Jquery和unobtrusiveAjax文件 已经默认开启客户端验证 和 非侵入式js <add key="ClientValidatio ...
- 吉特仓库管理系统-.NET4.0环境安装不上问题解决
在给客户实施软件的过程中要,要安装.NET 4.0 环境,而且是在XP的系统上. 目前的客户中仍然有大量使用XP的机器,而且极为不稳定,在安装吉特仓库管理系统客户端的时候出现了如下问题: 产品: Mi ...
- 项目分布式部署那些事(2):基于OCS(Memcached)的Session共享方案
在不久之前发布了一篇"项目分布式部署那些事(1):ONS消息队列.基于Redis的Session共享,开源共享",因为一些问题我们使用了阿里云的OCS,下面就来简单的介绍和分享下相 ...
- poj-1410 Intersection
计算几何的题目, 学cv的要做一下.poj 地址: http://poj.org/problem?id=1410 题意:判断一个直线段,是否与一个矩形有相交点. 解决方案: 判断矩形的每一条边是否与直 ...
- php 升级php5.5
rpm -Uvh http://mirror.webtatic.com/yum/el6/latest.rpm yum install php55w php55w-opcache yum install ...
- STL中algorithm里的查找
首先,选择查找算法时,区间是否排序是一个至关重要的因素.可以按是否需要排序区间分为两组: A. count,find B. binary_search,lower_bound,upper_bound, ...
- Webpack配置示例和详细说明
/* * 请使用最新版本nodejs * 默认配置,是按生产环境的要求设置,也就是使用 webpack -p 命令就可以生成正式上线版本. * 也可以使用 webpack -d -w 命令,生成用于开 ...
- PHP 异常
<?php /* PHP 异常处理 什么是异常? PHP 5 提供了一种新的面向对象的错误处理方法. 异常处理用于在指定的错误(异常)情况发生时改变脚本的正常流程. 这种情况称为异常. 当异常被 ...