码迷,mamicode.com
首页 > 其他好文 > 详细

CF125E MST company (凸优化+MST)

时间:2019-01-01 11:15:02      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:continue   define   har   efi   getc   怎么   过程   company   char   

qwq自闭的一个题

首先,我们可以把原图中的边,分成两类,一类是与\(1\)相连,另一类是不与\(1\)相连。

原题就转化成选择\(k\)条关键边的\(MST\)

那么我们可以按照tree I 那个题的思路来考虑这个题。

由于是\(MST\),所以函数满足下凸,那么对于这种恰好选\(k\)个的问题,我们可以直接凸优化。

\(erf\)一个值,然后把所有与1相连的边都加上这个值。

通过排序的时候把同权值的与1相连的边放到前面,那么通过二分,就能直接得到一个上界\(mid\),表示能选大于等于\(k\)条关建边的最小的\(mid\)

但是要是要求方案的话,应该怎么去做呢。

qwq有一个我不会证正确性的做法。

就是重新做一个\(,MST\)的过程。

如果当前已经选了\(k\)个与1相连的边,那么跳过后面所有与1相连的边!

qwq但是这个东西不是很理解啊
感觉坑点也很多。。
qwq
留个坑

#include<bits/stdc++.h>
#define pb push_back
#define mk make_pair
#define ll long long
#define int long long
using namespace std;
inline int read()
{
   int x=0,f=1;char ch=getchar();
   while (!isdigit(ch)){if (ch==‘-‘) f=-1;ch=getchar();}
   while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}
   return x*f;
}
const int maxn = 3e5+1e2;
struct Edge{
    int u,v;
    double w;
    int tag,num;
}; 
Edge e[maxn];int fa[maxn];int n,m,k;int val;
int find(int x)
{
    if (fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
bool cmp(Edge a,Edge b)
{
    if(a.w==b.w) return a.tag>b.tag;
    return a.w<b.w;
}
int solve()
{
    for (int i=1;i<=n;i++) fa[i]=i;
    sort(e+1,e+1+m,cmp);
    int tot=0;
    for (int i=1;i<=m;i++)
    {
        int f1 = find(e[i].u);
        int f2 = find(e[i].v);
        if (f1==f2) continue;
        if (e[i].tag && tot==k) continue;
        fa[f1]=fa[f2];
        tot+=e[i].tag; 
    }
    return tot;
}
vector<int> v;
signed main()
{
   n=read(),m=read(),k=read();
   double l = -1e10,r=1e10;
   int ymh=0;
   for (int i=1;i<=m;i++)
   {
       e[i].u=read(),e[i].v=read(),scanf("%lf",&e[i].w),e[i].num=i;
       if (e[i].u==1 || e[i].v==1) e[i].tag=1;
       if (e[i].tag==1) ymh++;
   }
   double ans=0;
   while(r-l>=1e-2)
   {
      double mid = (l+r)/2;
      for (int i=1;i<=m;i++) if(e[i].tag) e[i].w+=mid;
      int tmp = solve();
      if (tmp>=k) l=mid,ans=mid;
      else r=mid;
      for (int i=1;i<=m;i++) if (e[i].tag) e[i].w-=mid;
   }
   for (int i=1;i<=m;i++) if (e[i].tag) e[i].w+=ans;
   for (int i=1;i<=n;i++) fa[i]=i;
   sort(e+1,e+1+m,cmp);
   int val=0;
   for (int i=1;i<=m;i++)
   {
        int f1 = find(e[i].u);
        int f2 = find(e[i].v);
        if (f1==f2) continue;
        if (e[i].tag && val==k) continue;
        fa[f1]=fa[f2];
        val+=e[i].tag;
        v.pb(e[i].num);
   }
   if(val!=k || v.size()!=n-1) 
   {
     cout<<-1;
     return 0;
   }
   cout<<n-1<<endl;
   for (int i=0;i<v.size();i++) cout<<v[i]<<" ";
   return 0;
}
//final

CF125E MST company (凸优化+MST)

标签:continue   define   har   efi   getc   怎么   过程   company   char   

原文地址:https://www.cnblogs.com/yimmortal/p/10204210.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!