首页 > 其他分享 >洛谷P2323 [HNOI2006] 公路修建问题

洛谷P2323 [HNOI2006] 公路修建问题

时间:2024-10-08 22:01:09浏览次数:1  
标签:洛谷 int 边权 st P2323 高边权 HNOI2006 include type

Problem

给出n个点、m条边的无向连通图,每条边具有2个边权,一高一低,我们需要选择若干条边,使得图连通的情况下选择至少k条较高边权,输出选择的边中,边权最大值的最小值,输出答案的一半(保证偶数)

Slove

假设每条边只具有1条边权,答案显而易见,跑一遍最小生成树即可,因为最小生成树就是最小瓶颈树
但是如果存在较高边权且需要选至少k个,该怎么办呢?
注意到,Kruskal算法的本质就是贪心,每次选择最小的边,如果二点未连通,则用并查集合并,否则跳过,直到选择n-1条边
所以此时我们可以将所有边权都遍历一遍,当选择较高边权时k-1,如果k=还需要选择的边时,跳过所有较低边权......吗?
不难发现,此时最小生成树=最小瓶颈树不再适用,但我们可以按照这种贪心思路,优先选择k条较高边权,然后再根据需要选择剩下的边权(也包括较高边权,因为有时某一条边的较低边权可能比另一条边的较高边权还要高!)。因为k条高级边始终是要选择的,且高于低级边权。
时间复杂度就是Kruskal的时间复杂度,为\(O(nlogn)\)

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<list>
#include<map>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
int n,k,m,ans;
int f[10005];
struct p{
    int st,to,w,idx;
    bool type;
};
vector<p> g,road;
bool cmp(p a,p b){
    if(a.w!=b.w)
        return a.w<b.w;
    return a.type>b.type;
}
bool cmp1(p a,p b){
    return a.idx<b.idx;
}
int find(int u){
    if(f[u]==u)return u;
    return f[u]=find(f[u]);
}
bool same(int u,int v){
    return find(u)==find(v);
}
bool unit(int u,int v){
    if(same(u,v))return false;
    f[find(u)]=v;
    return true;
}
void kruskal(){
    int edge=n-1;
    for(int i=0;i<g.size();i++){
        if(k>0&&!g[i].type){
            continue;
        }
        if(k==0){
            i=0;
            k--;
        }
        if(unit(g[i].st,g[i].to)){
            k-=g[i].type;
            edge--;
            ans=max(ans,g[i].w);
            road.push_back(g[i]);
        }
        if(!edge)break;
    }
}
int main(){
    cin>>n>>k>>m;
    for(int i=1;i<=n;i++)f[i]=i;
    for(int i=1,st,to,w1,w2;i<m;i++){
        cin>>st>>to>>w1>>w2;
        g.push_back({st,to,w1,i,1});
        g.push_back({st,to,w2,i,0});
    }
    sort(g.begin(),g.end(),cmp);
    kruskal();
    cout<<ans<<endl;
    sort(road.begin(),road.end(),cmp1);
    for(int i=0;i<road.size();i++){
        int type;
        if(road[i].type==1)type=1;
        else type=2;
        cout<<road[i].idx<<" "<<type<<endl;
    }
    return 0;
}

标签:洛谷,int,边权,st,P2323,高边权,HNOI2006,include,type
From: https://www.cnblogs.com/yiweixxs/p/18453136

相关文章

  • 洛谷P2513 逆序对数列
    Problem给定n,k,求得1~n中有多少种排列使得逆序对个数为k?(n,k<=1000)Solve考虑DP:设f[i][j]为i个数中逆序对数量为j的排列数量但因为我们并不知道我们这i个数到底是谁,难以通过以前的状态得到设f[i][j]为将i放入之前的排列后,逆序对数量为k的排列数此时我们发现可以确定前i-1......
  • 【模板】回文自动机(PAM)(洛谷P5496)
    #include<bits/stdc++.h>#defineendl'\n'#defineintllusingll=longlong;typedefunsignedlonglongull;usingnamespacestd;voidGordenGhost();constexprllN=5e5+7;namespacePAM{intsize,tot,last;//last:最新插入的字母的编号......
  • 洛谷 P3523 题解
    洛谷P3523[POI2011]DYN-Dynamite分析二分答案,问题转化为:对于给定的\(K\),选择尽可能少的节点,使得所有关键节点都被「覆盖」。对于一个关键节点,「覆盖」的定义为:存在一个被选择的点与这个关键节点的距离不大于\(K\)。方便起见,我们指定\(1\)号节点是这棵树的根节点。我们......
  • 20241006每日一题洛谷P1031
    对题目第一印象:贪心吧,或者纯模拟第一次贪心,由于左右端堆只能想内一堆移动,遂放弃第一次模拟,开多个数组,(可能还要用递归?),遂放弃于是求助如来佛祖:从逻辑上可以看出,第一堆缺或者多的牌只能移动到第二堆上当第一堆达到期望值时,第一堆便不能再做操作,于是,可以将第二堆作为第一堆来处理......
  • 20241002每日一题洛谷P1563
    粗看题目我靠,什么方向还变来变去的(哭泣核心思想:圈内右数,圈外左数为整体逆时针数;圈外右数,圈内左数为整体顺时针数运用结构体就有了第一版源码:structpeople{ intface; charname[12];};intmain(){ intm,n; scanf("%d%d",&n,&m); peoplea[10010]; for(inti......
  • [题解][洛谷P3584] LAS
    题目描述有n个蛋糕和n个人,每个蛋糕的热量是Ci。第i个人可以选择吃第i或第i+1个蛋糕,第n个人可以选择吃第n或第1个蛋糕。若一个蛋糕被两个人吃,那么每个人得到的热量是Ci/2.若一个人改变自己的选择,得到的热量增加,那么他会不满意。试输出让所有人满意的解,输出每个人吃蛋糕的序号......
  • [题解][洛谷P1578] 奶牛浴场
    题目描述在长宽为L,W的二维平面上有n个障碍点,试找到一个不覆盖任何障碍点(但点可以在边缘线上的)面积最大的矩形(长宽均与坐标轴平行)。输出面积。题意分析n的范围在5e3,考虑O(n2)的做法。易得面积最大的矩形四条边要么有障碍点,要么覆盖的边界。否则四条边可以继续扩展,面积会变得更......
  • [题解][洛谷P1633] 二进制
    题目描述有三个整数A,B,C,构造三个整数X,Y,Z满足:1.A,B,C在二进制下1的数量分别与X,Y,Z相等;2.X,Y,Z在二进制下的长度不超过A,B,C的最大长度;3.X+Y=Z。输出Z的最小值,若不存在Z,输出-1。题意分析首先考虑X,Y在什么情况下会使1的数量发生改变。设x,y,z分别表示X,Y,Z中1的数量,则......
  • 洛谷P10336 [UESTCPC 2024] 2-聚类算法
    涉及知识点:博弈、贪心题意Alice和Bob在玩选点游戏,所有的点在一个\(k\)维空间中,他们轮流选走一个点放入自己的集合中,Alice先手。定义集合\(S\)的权值\(val(S)\)为集合中点两两之间的\(k\)维曼哈顿距离之和。Alice的得分为\(val(S_A)-val(S_B)\),Bob的得分为\(val(......
  • 题解:洛谷P2339 [USACO04OPEN] Turning in Homework G
    题目链接:洛谷P2339[USACO04OPEN]TurninginHomeworkG首先我们考虑如何处理到达给定时间后才能交作业这一限制。其实在生活中,我们一般只会考虑什么时候交作业截止(除了某些卷王),这样我们只用考虑如何在最大结束时间之前交作业,而不是在所有作业都没开始交之前考虑如何转悠(前者明......