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 ...
随机推荐
- [py]特殊函数+文件保护
1函数的好处 2函数的全局变量和局部变量 3,包和文件夹的区别 4,__name__ __file__ __doc__ #判断是否为主程序 if __name__=='__main__': pass ...
- Ubuntu环境下安装TinyOS系统
1.输入下面命令会弹出source list窗口 1 sudo gedit /etc.apt/sources.list 在尾部添加以下地址: 1 2 deb http://tinyos.sta ...
- c++多重继承小结
如果一个类从两个不同的类里继承两个同名的成员,则需要在派生类中使用类限定符来区分他们. 即在从A和B派生出来的c类中使用a::Show()和B::Show()来区分从这两个类那里继承的show()方法 ...
- DOM 元素节点几何量与滚动几何量
当在 Web 浏览器中查看 HTML 文档时,DOM 节点被解析,并被渲染成盒模型(如下图),有时我们需要知道一些信息,比如盒模型的大小,盒模型在浏览器中的位置等等,本文我们就来详细了解下元素节点的几 ...
- 【前端也要学点算法】快速排序的JavaScript实现
作为算法目录下的第一篇博文,快速排序那是再合适不过了.作为最基本最经典的算法之一,我觉得每个程序员都应该熟悉并且掌握它,而不是只会调用库函数,知其然而不知其所以然. 排序算法有10种左右(或许更多), ...
- Asp.net Mvc中利用ValidationAttribute实现xss过滤
在网站开发中,需要注意的一个问题就是防范XSS攻击,Asp.net mvc中已经自动为我们提供了这个功能.用户提交数据时时,在生成Action参数的过程中asp.net会对用户提交的数据进行验证,一旦 ...
- 基于DDD的.NET开发框架 - ABP Session实现
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- pay-as-you-go
What is pay as you go? A pay as you go deal means you aren’t tied into a contract and can top up you ...
- VMware精简系统Win系列|体积更小更稳定
此Win系列基于VMware10 给个我自用的超精简VM10.0.3 XP重新制作体积大了一点但更稳定,压缩包166M 制作了Win 2003,压缩包171.4M Win7重新制作体积更小更稳定,压缩 ...
- No goals have been specified for this build
在pom.xml文件中build后面加上<defaultGoal>compile</defaultGoal>