牛客小白月赛69

发布时间 2023-10-31 16:51:45作者: 畴

D题

D-旅游_牛客小白月赛69(重现赛)@PHarr (nowcoder.com)

题意:自己看

题解:最小生成树模板题

最小生成树算法(这个就是给你一个图里面修路让城市和城市之间想联通,每一条路都是有一个修路的花费,最小生成树就是全部的点联通最小的代价)

现在怎么处理

首先我们排序每一个连接的边的代价进行从小到大排序

然后开始枚举如果再两个点不在一个树里面,那么我们就需要加上这个边的代价,然后把这点连到树里面(这里我们用并查集进行处理,find函数找父节点加边)

然后你就会得到这个情况下的最小的代价

这题我们需要二分政府给的花费,带入最小生成树里面判断结果即可

 

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=3e6+7,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=100003;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a%p;
    }
    return ans;
}
typedef pair<int,int> PII;


int fu[N];
int ch[N];
int n,m,c;
struct G{
    int x,y,val;
}a[N];
int find(int x) {
    if (fu[x] == x) return x;
    else return fu[x] = find(fu[x]);
}
bool cmp(G x,G y)
{
    return x.val<y.val;
}

bool kruskal(int x)
{
    for(int i=1;i<=n;i++)
    {
        fu[i]=i;
    }
    int ans=0;
    int k=0;
    for(int i=1;i<=m;i++)
    {
        int x1=a[i].x,y1=a[i].y,c1=a[i].val;

        x1=find(x1),y1=find(y1);
        if(x1!=y1)
        {
            fu[x1]=y1;
            if(c1>x)
            {
                ch[++k]=c1;
            }
        }
    }
    for(int i=k;i>=1;i--)
    {
        ans+=(k+1-i)*ch[i];
    }
    return ans<=c;
}

void solve()
{

    cin>>n>>m>>c;

    for(int i=1;i<=m;i++)
    {
        int x,y,val;
        cin>>x>>y>>val;
       a[i]={x,y,val};
    }
    sort(a+1,a+1+m,cmp);

    int l=0,r=1e9;
    while (l<r)
    {
        int mid=(l+r)/2;
        if(kruskal(mid)) r=mid;
        else l=mid+1;
    }
    cout<<l<<endl;
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}