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 ...
随机推荐
- swift 集合类型(二)
说到swift的集合类型,就不得不谈到Dictionary.包含一个键值对组合的集合. var air = ["name":"warner","tit ...
- [转]nginx+fastcgi+c/c++搭建高性能Web框架
FROM : http://blog.csdn.net/marising/article/details/3932938 1.Nginx 1.1.安装 Nginx 的中文维基 http://wiki. ...
- <实训|第十天>从底层解释一下U盘内存为什么变小的原因附数据恢复的基本原理
[root@localhost~]#序言 我们平时不论是买一个U盘硬盘,或者自己在电脑上创建一个分区,大小总是比我们创建的要小一点,有些人会说,这个正常啊,是因为厂家规定的1M=1000k,真正的是1 ...
- iis7配置网站容易出现的问题(转)
来源: http://www.cnblogs.com/5426z/articles/4865022.html 1.64位操作系统 access数据库提示:未在本地计算机上注册"Microso ...
- sql 重复数据只保留一条
用SQL语句,删除掉重复项只保留一条在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select * ...
- e.stopPropagation();与 e.preventDefault();
e.stopPropagation()阻止事件冒泡 <head> <title></title> <script src="Scripts/jque ...
- make the innerText in the html element can not be selected
approach style="-moz-user-select:none;" onselectstart="javascript:return false;" ...
- Alpha版本冲刺现场演示和阶段验收的总结
一共15个组.有13个组参加了今天的现场演示,分别是YZH.Radio Group.FZU5BOYS.静静看.Clean Code.Mod4.F4.For the Dream.Journey of C ...
- my-Life项目开发流程
一:新建java web项目 (懂得使用gradle哦!) 1.http://www.cnblogs.com/xylle/p/5234380.html 2.新建项目后,然后新建module, 如果甲 ...
- Qt自定义窗体,边框,圆角窗体
MainWindow::MainWindow(QWidget*parent): QMainWindow(parent), ui(new Ui::MainWindow) { setAttribute(Q ...