E. MST Company
time limit per test 8 seconds
memory limit per test 256 megabytes
input standard input
output standard output

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.

Input

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.

Output

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.

Examples
input
4 5 2
1 2 1
2 3 1
3 4 1
1 3 3
1 4 2
output
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的更多相关文章

  1. CODEFORCES 125E MST Company 巧用Kruskal算法

    题意:给定一个带权边无向图,求最小生成树,且满足第一个节点的度为固定的k 无解则输出-1 数据规模: 节点数n和限制k<=5000 边数m<=10^5 时限8sec 思路: 首先时限比较宽 ...

  2. 【CF125E】MST Company(凸优化,最小生成树)

    [CF125E]MST Company(凸优化,最小生成树) 题面 洛谷 CF 题解 第一眼看见就给人丽洁姐那道\(tree\)一样的感觉. 那么二分一个权值,加给所有有一个端点是\(1\)的边, 然 ...

  3. Codeforces 1108F MST Unification MST + LCA

    Codeforces 1108F MST + LCA F. MST Unification Description: You are given an undirected weighted conn ...

  4. luogu CF125E MST Company wqs二分 构造

    LINK:CF125E MST Company 难点在于构造 前面说到了求最小值 可以二分出斜率k然后进行\(Kruskal\) 然后可以得到最小值.\(mx\)为值域. 得到最小值之后还有一个构造问 ...

  5. Codeforces 556D Restructuring Company

    传送门 D. Restructuring Company time limit per test 2 seconds memory limit per test 256 megabytes input ...

  6. [刷题]Codeforces 794C - Naming Company

    http://codeforces.com/contest/794/problem/C Description Oleg the client and Igor the analyst are goo ...

  7. Codeforces 1108F MST Unification(最小生成树性质)

    题目链接:MST Unification 题意:给定一张连通的无向带权图.存在给边权加一的操作,求最少操作数,使得最小生成树唯一. 题解:最小生成树在算法导论中有这个性质: 把一个连通无向图的生成树边 ...

  8. Codeforces 1062 E - Company

    E - Company 思路: 首先,求出每个点的dfs序 然后求一些点的公共lca, 就是求lca(u, v), 其中u是dfs序最大的点, v是dfs序最小的大点 证明: 假设o是这些点的公共lc ...

  9. [CF125E]MST Company

    codeforces description 给出一张\(n\)点\(m\)条边的无向图,求一棵满足\(1\)号点度数恰好为\(k\)的最小生成树,并输出方案. \(1\le k\le n\le500 ...

随机推荐

  1. filestream read方法 循环读取固定文件

    1.循环读取啊,byte[]可以定义为1024或者2049等等,不要超过int的maxvalue就可以.然后取出来操作完再去取. FileStream stream = new FileStream( ...

  2. 关于div标签的title属性一闪一闪不正常显示的原因

    弹出了chrome的开发工具就会出现以上问题.

  3. IBM WebSphere MQ 7.5基本用法

    一.下载7.5 Trial版本 http://www.ibm.com/developerworks/downloads/ws/wmq/ 这是下载网址,下载前先必须注册IBM ID,下载完成后一路Nex ...

  4. 谱多流形聚类SMMC

    今天是2015年的最后一天,决定尽量乘着这三天休息把毕设主题的博客给更完,今天写smmc的算法,接下来三天会对前面的三个算法kmeans.SC以及smmc应用在今年的研究生建模提供的数据中进行matl ...

  5. Struts2 动态结果和带参数的跳转

    完整代码:Struts16ActionResultsDemo.rar 1.动态结果. 有时我们需要在Action里取得我个要转跳的页面 看一下我们的struts.xml <?xml versio ...

  6. 将DBF文件导入Sqlserver数据库

    项目中的问题:用户选择N个dbf文件导入sql2005数据库,由于每年dbf表结构都在变化,所以在sql2005中根本就不存在,需要每年根据dbf的结构自动建表.(文章来自http://blog.cs ...

  7. NHibernate无法将类型“System.Collections.Generic.IList<T>”隐式转换为“System.Collections.Generic.IList<IT>

    API有一个需要实现的抽象方法: public IList<IPermission> GetPermissions(); 需要注意的是IList<IPermission>这个泛 ...

  8. 如何解决Windows 10系统下设备的声音问题

    如何解决Windows 10系统下设备的声音问题? 请阅读下面的说明来解决Windows 10设备上的声音问题. 1. 检查设备管理器 打开开始菜单,键入设备管理器, 从出现的结果中选择并打开它. 在 ...

  9. HTTP 错误 500.24 - Internal Server Error的解决方法

    错误提示: 最可能的原因:   system.web/identity@impersonate 设置为 true. 解决办法: 现在经典模式 连微软都几乎放弃了 原设想是为iis不断升级 提供的一种兼 ...

  10. Project Serve 2013部署方法

    在线版Project2013部署手册 服务器环境要求 系统:windows server 2008r2.windows server2012x64 Sharepoint 2013 内存至少16GB,最 ...