ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces GYM 100876 J - Buying roads 题解

2020-10-06 10:34:16  阅读:254  来源: 互联网

标签:node cur int 题解 GYM hang Codeforces heap ans


Codeforces GYM 100876 J - Buying roads 题解

才不是因为有了图床来测试一下呢,哼(

题意

给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得得到的子图联通并且总代价最小,输出最小总代价和一种方案。

虽然题目里描述的很冗长,但其实这个图有一些性质:它最初是一条链/一个环,然后再有一些结点直接连到这些在链上/环上的结点。、

下图就是一个(就是样例):

image-20201006101016651

做法

首先我们可以简单的查看点的度数来找到链/环上的点,和连接它们的边。

然后我们可以通过对链的头和尾添加一条权值大到足够保证不会选到它的边,把链变成环(样例被更改的样子):

image-20201006101401687

我们可以枚举选择的是环上的相连的一条链,选择这些环上的边的同时,也贪心地从小到大选择挂在环上(类似于连接\(8\)和\(9\))的边。

这里可以枚举链的起点,在不断扩展这条链的右端点(并强制选取达到的它的边)的同时,维护一个堆,堆里存放的是选择的链上挂的边的权值最大值,每次添加时去查看添加的边的权值是否小于这个最大值,然后更新这个堆即可。

需要注意有选择整个环而非一部分的链的方案。

程序

这里把计算答案和构造方案分开了,实现起来可能比较方便。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

int n,m,K;
vector<pair<int,int>> g[2005];
vector<int> hang[2005];
vector<int> node,edge;
ll w[2005],ans=1e18;

void get_imp(const int &x,const int &p,const int &head){
    node.emplace_back(x);
    for(pair<int,int> &e:g[x]){
        if(e.first!=p&&g[e.first].size()>1){
            edge.emplace_back(e.second);
            if(e.first!=head)get_imp(e.first,x,head);
            return;
        }
    }
}

void get_ans_val(){
    priority_queue<int> heap;
    ll cur;
    for(int i=0;i<node.size();i++){
        while(!heap.empty())heap.pop();
        cur=0;
        for(int jj=i;jj<i+K&&jj<i+node.size();jj++){
            int j=jj%node.size();
            for(int k=0;k<hang[node[j]].size();k++){
                if(heap.size()+jj-i<K){
                    heap.emplace(w[hang[node[j]][k]]);
                    cur+=w[hang[node[j]][k]];
                }else if(heap.top()>w[hang[node[j]][k]]){
                    cur-=heap.top();
                    heap.pop();
                    cur+=w[hang[node[j]][k]];
                    heap.emplace(w[hang[node[j]][k]]);
                }else break;
            }
            if(heap.size()+jj-i==K){
                ans=min(ans,cur);
                cur-=heap.top();
                heap.pop();
            }
            cur+=w[edge[j]];
        }
        ans=min(ans,cur);
    }
}

void construct(set<int> &use){
    priority_queue<pair<int,int>> heap;
    ll cur;
    for(int i=0;i<node.size();i++){
        while(!heap.empty())heap.pop();
        cur=0;
        use.clear();
        for(int jj=i;jj<i+K&&jj<i+node.size();jj++){
            int j=jj%node.size();
            for(int k=0;k<hang[node[j]].size();k++){
                if(heap.size()+jj-i<K){
                    heap.emplace(w[hang[node[j]][k]],hang[node[j]][k]);
                    use.insert(hang[node[j]][k]);
                    cur+=w[hang[node[j]][k]];
                }else if(heap.top().first>w[hang[node[j]][k]]){
                    cur-=heap.top().first;
                    use.erase(heap.top().second);
                    heap.pop();
                    cur+=w[hang[node[j]][k]];
                    heap.emplace(w[hang[node[j]][k]],hang[node[j]][k]);
                    use.insert(hang[node[j]][k]);
                }else break;
            }
            if(heap.size()+jj-i==K){
                if(cur==ans)return;
                cur-=heap.top().first;
                use.erase(heap.top().second);
                heap.pop();
            }
            cur+=w[edge[j]];
            use.insert(edge[j]);
        }
        if(cur==ans)return;
    }
}

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    if(fopen("roads.in","r")){
        freopen("roads.in","r",stdin);
        freopen("roads.out","w",stdout);
    }

    cin>>n>>m>>K;
    for(int i=1;i<=m;i++){
        static int u,v,W;
        cin>>u>>v>>W;
        g[u].emplace_back(v,i);
        g[v].emplace_back(u,i);
        w[i]=W;
    }
    for(int i=1;i<=n;i++){
        if(g[i].size()==1)hang[g[i].front().first].emplace_back(g[i].front().second);
        else if(node.empty()){
            int cnt=0;
            for(pair<int,int> &e:g[i])cnt+=g[e.first].size()>1;
            if(cnt==1)get_imp(i,-1,i);
        }
    }
    if(node.empty())for(int i=1;i<=n;i++){
        if(g[i].size()>1){
            get_imp(i,-1,i);
            break;
        }
    }
    if(edge.size()+1==node.size()){
        edge.emplace_back(++m);
        w[m]=1e15;
    }
    for(int i=1;i<=n;i++)sort(hang[i].begin(),hang[i].end(),[](const int &a,const int &b){
        return w[a]<w[b];
    });
    get_ans_val();
    cout<<ans<<'\n';
    set<int> s;
    construct(s);
    for(const int &x:s)cout<<x<<'\n';

    return 0;
}

标签:node,cur,int,题解,GYM,hang,Codeforces,heap,ans
来源: https://www.cnblogs.com/BlahDuckling747/p/13772820.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有