zoukankan      html  css  js  c++  java
  • 【CF125E】MST Company(凸优化,最小生成树)

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

    题面

    洛谷
    CF

    题解

    第一眼看见就给人丽洁姐那道(tree)一样的感觉。
    那么二分一个权值,加给所有有一个端点是(1)的边,
    然后跑最小生成树(check)一下就好了。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define MAX 5050
    #define MAXL 100100
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    struct edge{int u,v,w,id;}e[MAXL];
    bool operator<(edge a,edge b)
    {
    	if(a.w!=b.w)return a.w<b.w;
    	return a.u>b.u;
    }
    int f[MAX],n,m,K,tot;
    int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
    vector<int> g;
    int Kruskal(int mid)
    {
    	for(int i=1;i<=m;++i)if(e[i].u==1)e[i].w+=mid;
    	for(int i=1;i<=n;++i)f[i]=i;
    	int cnt=0;g.clear();sort(&e[1],&e[m+1]);
    	for(int i=1;i<=m;++i)
    	{
    		int u=getf(e[i].u),v=getf(e[i].v);
    		if(u==v)continue;
    		f[u]=v;g.push_back(e[i].id);
    		if(e[i].u==1)++cnt;
    	}
    	for(int i=1;i<=m;++i)if(e[i].u==1)e[i].w-=mid;
    	return cnt;
    }
    void Calc(int mid)
    {
    	for(int i=1;i<=m;++i)if(e[i].u==1)e[i].w+=mid;
    	for(int i=1;i<=n;++i)f[i]=i;
    	int cnt=0,tot=0;g.clear();sort(&e[1],&e[m+1]);
    	for(int i=1;i<=m;++i)
    	{
    		int u=getf(e[i].u),v=getf(e[i].v);
    		if(u==v)continue;
    		if(e[i].u==1&&cnt==K)continue;
    		f[u]=v;g.push_back(e[i].id);
    		if(e[i].u==1)++cnt;++tot;
    	}
    	if(cnt<K||tot!=n-1){puts("-1");exit(0);}
    }
    int main()
    {
    	n=read();m=read();K=read();
    	for(int i=1;i<=m;++i)
    	{
    		int u=read(),v=read(),w=read();
    		if(u>v)swap(u,v);if(u==1)++tot;
    		e[i]=(edge){u,v,w,i};
    	}
    	int l=-100000,r=100000,ret=-1e9;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		int d=Kruskal(mid);
    		if(d<K)r=mid-1;
    		else l=mid+1,ret=mid;
    	}
    	if(ret<-1e5){puts("-1");return 0;}
    	Calc(r);printf("%d
    ",n-1);
    	for(int i=0;i<n-1;++i)printf("%d ",g[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    token认证、JWT
    DRF序列化、认证、跨域问题
    JS 作用域 p1
    如何配置图标
    关于批量更新与删除
    windows 公司内部搭建禅道(项目管控)
    JS 创建自定义对象的方式方法
    apicloud 消息推送与接收
    apicloud 自定义模块的开发与上架注意事项
    apicloud 第一篇
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9438074.html
Copyright © 2011-2022 走看看