Concurso de programación de sitios ICPC Asia Taipei-Hsinchu 2020 H. Optimización para UltraNet (dos puntos + árbol de expansión mínimo + contribución de cálculo)

Concurso de programación de sitios ICPC Asia Taipei-Hsinchu 2020 H. Optimización para UltraNet (dos puntos + árbol de expansión mínimo + contribución de cálculo)

Enlace del título original

Título:

Encuentre el árbol de expansión de modo que el peso mínimo de los bordes sea el más grande y, sobre esta base, la suma de los pesos de los bordes más cortos en cualquier ruta de dos puntos sea la más pequeña. Encuentre la suma de los pesos laterales más cortos en la trayectoria de dos puntos cualesquiera.

Ideas:

El lado más pequeño tiene el mayor peso y es fácil pensar en una dicotomía.

La posición del peso de borde mínimo dicotómico se comprueba cada vez si puede constituir un árbol de expansión.

Para el cálculo de la respuesta, considere la contribución de cada borde. Ordene los bordes seleccionados de pequeños a grandes. Si el borde actual puede conectar dos bloques conectados, la contribución del borde actual es w * siz [fu] * siz [fv].

Código:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;typedef unsigned long long ull;
typedef pair<ll,ll>PLL;typedef pair<int,int>PII;typedef pair<double,double>PDD;
#define I_int ll
inline ll read(){
    
    ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){
    
    if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
    
    x=x*10+ch-'0';ch=getchar();}return x*f;}
#define read read()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
ll ksm(ll a,ll b,ll p){
    
    ll res=1;while(b){
    
    if(b&1)res=res*a%p;a=a*a%p;b>>=1;}return res;}
const int maxn=1e6+7;

struct node{
    
    
    ll u,v,w;
}edge[maxn];
bool cmp(node a,node b){
    
    
    return a.w<b.w;
}
bool cmp1(node a,node b){
    
    
    return a.w>b.w;
}
int n,m,root[maxn];

int Find(int x){
    
    
    if(x!=root[x]) root[x]=Find(root[x]);
    return root[x];
}

int h[maxn],idx;
struct node1{
    
    
    ll e,ne,w;
}edge1[maxn];
void add1(int u,int v,int w){
    
    
    edge1[idx]={
    
    v,h[u],w};h[u]=idx++;
}

bool check(int mid){
    
    
    if(m-mid+1<n-1) return 0;
    int cnt=0;
    rep(i,1,n) root[i]=i;
    rep(i,mid,m){
    
    
        int u=edge[i].u,v=edge[i].v,w=edge[i].w;
        int fu=Find(u),fv=Find(v);
        if(fu!=fv){
    
    
            root[fu]=fv;
            cnt++;
            //add1(u,v,w);add1(v,u,w);
        }
        if(cnt==n-1) break;
    }
    if(cnt==n-1) return 1;
    return 0;
}
ll siz[maxn];
void solve(){
    
    
    n=read,m=read;
    //rep(i,1,n) root[i]=i;
    rep(i,1,m){
    
    
        ll u=read,v=read,w=read;
        edge[i]={
    
    u,v,w};
    }
    sort(edge+1,edge+1+m,cmp);
    int l=1,r=m,ans;//枚举最短边所在的位置
    //最短边最长
    while(l<=r){
    
    
        int mid=(l+r)/2;
        if(check(mid)){
    
    //还可以更长
            ans=mid;l=mid+1;
        }
        else r=mid-1;
    }

    memset(h,-1,sizeof h);
    int cnt=0;
    rep(i,1,n) root[i]=i;
    rep(i,ans,m){
    
    
        ll u=edge[i].u,v=edge[i].v,w=edge[i].w;
        int fu=Find(u),fv=Find(v);
        if(fu!=fv){
    
    
            root[fu]=fv;
            cnt++;
           // add1(u,v,w);add1(v,u,w);
           edge[cnt]={
    
    u,v,w};
        }
        if(cnt==n-1) break;
    }
    sort(edge+1,edge+1+cnt,cmp1);
    ll res=0;
    rep(i,1,n) root[i]=i,siz[i]=1;
    rep(i,1,cnt){
    
    
        ll u=edge[i].u,v=edge[i].v,w=edge[i].w;
        int fu=Find(u),fv=Find(v);
        if(fu!=fv){
    
    
            root[fu]=fv;
            res=res+w*siz[fu]*siz[fv];
            siz[fv]+=siz[fu];
        }
    }
    printf("%lld\n",res);
}
int main(){
    
    
    int T=1;
    while(T--) solve();
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45675097/article/details/113862012
Recomendado
Clasificación