小 X 的道路修建

Posted 殇雪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小 X 的道路修建相关的知识,希望对你有一定的参考价值。

 

题目描述

因为一场不小的地震, Y 省 n 个城市之间的道路都损坏掉了,省长希望小 X 将城市之间的道路重 修一遍。 很多城市之间的地基都被地震破坏导致不能修路了,因此可供修建的道路只有 m 条。因为施工队伍 有限,省长要求用尽量少的道路将所有的城市连通起来,这样施工量就可以尽量少。不过,省长为了表 示自己的公正无私,要求在满足上述条件的情况下,选择一种方案,使得该方案中最贵道路的价格和最 便宜道路的价格的差值尽量小,即使这样的方案会使总价提升很多也没关系。 小 X 现在手忙脚乱,希望你帮帮他。

输入

第一行包含两个整数 n; m。 接下来 m 行,每行包含三个整数 a; b; c,表示城市 a; b 之间可以修建一条价格为 c 的无向道路。

输出

若存在合法方案,则第一行包含一个整数,表示最贵道路的价格和最便宜道路的价格的最小差值; 否则第一行包含一个整数 −1。

样例输入

5 10 1 2 9384 1 3 887 1 4 2778 1 5 6916 2 3 7794 2 4 8336 2 5 5387 3 4 493 3 5 6650 4 5 1422

样例输出

1686
LCT 裸题。
#pragma GCC optimize("-Ofast")
#include<bits/stdc++.h>
#define N 910007
using namespace std;
int n,m,ans=INT_MAX,ti;
void read(int &x){
    static char c; static int b;
    for (b=1,c=getchar();!isdigit(c);c=getchar()) if (c==-) b=-1;
    for (x=0;isdigit(c);c=getchar()) x=x*10+c-48;
    x*=b;
}
struct edge{
    int x,y,z;
    inline bool operator <(const edge& A)const{
       return z<A.z;
    }
}e[N];
namespace snow{
int ch[N][2],fa[N],r[N],mi[N],val[N],id,usd[N];
bool isroot(int x){
    return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
}
void rev(int x){
    r[x]^=1; swap(ch[x][0],ch[x][1]);
}
void pushdown(int x){
    if (!isroot(x)) pushdown(fa[x]);
    if (r[x]) {
        if (ch[x][0]) rev(ch[x][0]);
        if (ch[x][1]) rev(ch[x][1]);
        r[x]=0;
    }
}
void pushup(int x){
    mi[x]=val[mi[ch[x][0]]]<val[mi[ch[x][1]]]?mi[ch[x][0]]:mi[ch[x][1]];
    mi[x]=val[mi[x]]<val[x]?mi[x]:x;
}
void rotate(int x){
    int y=fa[x],z=fa[y],l,r;
    if (ch[y][0]==x) l=0; else l=1;
    r=l^1;
    if (!isroot(y)) ch[z][ch[z][1]==y]=x;
    fa[x]=z; fa[ch[x][r]]=y; fa[y]=x;
    ch[y][l]=ch[x][r]; ch[x][r]=y;
    pushup(x); pushup(y);
}
void splay(int x){
    pushdown(x);
    while (!isroot(x)) {
        int y=fa[x],z=fa[y];
        if (!isroot(y)) {
         if (ch[y][0]==x^ch[z][0]==y) rotate(x);
         else rotate(y);}
        rotate(x);
    }
}
void access(int x) {
    int y=0;
    while (x) {
        splay(x);
        ch[x][1]=y;
        pushup(x); 
        y=x;
        x=fa[x];
    }
}
void beroot(int x){
    access(x); splay(x); rev(x);
}
int root(int x) {
    access(x); splay(x); while (ch[x][0]) x=ch[x][0]; return x; 
}
void link(int x,int y){
    beroot(x); fa[x]=y;
}
void cut(int x,int y){
   beroot(x);
   access(y); splay(y);
   if (ch[y][0]==x) ch[y][0]=0;
   fa[x]=0;
} 
void sol() {
    for (int i=1;i<=m;i++)
     read(e[i].x),read(e[i].y),read(e[i].z);
    sort(e+1,e+m+1); ans=INT_MAX;
    for (int i=0;i<=n;i++) val[i]=INT_MAX;
    for (int i=1;i<=m;i++) val[n+i]=e[i].z;
    int to=1;
    for (int i=1;i<=m;i++) {
        beroot(e[i].x); 
        if (root(e[i].y)!=e[i].x) {
            link(n+i,e[i].x);
            link(n+i,e[i].y); ti++;
        }else {
            id=mi[e[i].y]; usd[id-n]=1;
            cut(id,e[id-n].x);
            cut(id,e[id-n].y);
            link(n+i,e[i].x);
            link(n+i,e[i].y);
        }
       while (usd[to]) to++;
       if (ti==n-1) ans=min(ans,e[i].z-e[to].z);
    }
   printf("%d\n",ans==INT_MAX?-1:ans);
}
}
signed main () {
    read(n); read(m);
    snow::sol();
}

 

以上是关于小 X 的道路修建的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P2052 道路修建

NOI2011道路修建 BFS

图论 洛谷P2052 道路修建

NOIp2011道路修建

[NOI2011]道路修建

BZOJ 1626 [Usaco2007 Dec]Building Roads 修建道路:kruskal(最小生成树)