【JZOJ3806】小X 的道路修建

Description

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

Solution

首先最小生成树上最大的边最小。

排序后从大到小加边,如果出现了环,那么当前的边可以代替环上最大的边,然后如果图中有n-1条边就统计答案。

那么树上动态加边,可以暴力做,范围不大。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define rep(i,x) for(int i=ls[x];i;i=nx[i])
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 2010
#define M 30010
using namespace std;
struct node{
    int u,v,w;
}e[M];
bool cmp(node x,node y){
    return x.w<y.w;
}
int fr[M],to[M],nx[M],ls[N],val[M],ls1[M],num=0;
int zd,mx,c,n,o=0;
bool bz[M];
void link(int x,int y,int c)
{
    num++;
    fr[num]=x;
    to[num]=y;
    nx[num]=ls[x];
    ls1[ls[x]]=num;
    ls[x]=num;
    val[num]=c;
}
bool jy;
void dfs(int x,int fa)
{
    if(x==zd)
    {
        jy=true;
        return;
    }
    rep(i,x)
    if(!bz[i])
    {
        o++;
        int v=to[i];
        if(v!=fa)
        {
            int t1=mx,t2=c;
            if(mx<val[i]) mx=val[i],c=i;
            dfs(v,x);
            if(jy) return;
            mx=t1,c=t2;
        }
    }
}
int g(int x){
    return x%2?(x+1):(x-1);
}
void find(int x,int fa)
{
    rep(i,x)
    if(!bz[i])
    {
        int v=to[i];
        if(v!=fa)
        {
            if(mx<val[i]) mx=val[i];
            find(v,x);
        }
    }
}
int main()
{
    int m;
    scanf("%d %d",&n,&m);
    fo(i,1,m)
    {
        int u,v,w;
        scanf("%d %d %d",&u,&v,&w);
        e[i].u=u,e[i].v=v,e[i].w=w;
    }
    sort(e+1,e+m+1,cmp);
    int t=0;
    int ans=2147483647,gg=0;
    fd(i,m,1)
    {
        zd=e[i].v;
        int u=e[i].u,v=e[i].v,w=e[i].w;
        mx=0;
        o=0;
        jy=false;
        dfs(u,0);
        if(jy)
        {
            t--;
            if(!ls1[c]) ls[fr[c]]=nx[c];
            else nx[ls1[c]]=nx[c];
            if(nx[c]) ls1[nx[c]]=ls1[c];
            c=g(c);
            if(!ls1[c]) ls[fr[c]]=nx[c];
            else nx[ls1[c]]=nx[c];
            if(nx[c]) ls1[nx[c]]=ls1[c];
        }
        link(u,v,w);
        link(v,u,w);
        t++;
        if(t==n-1)
        {
            mx=0;
            find(u,0);
            if(ans>mx-w) ans=mx-w;
        }
    }
    if(ans==2147483647) printf("-1");
    else printf("%d",ans);
}
posted @ 2017-01-09 19:27  sadstone  阅读(53)  评论(0编辑  收藏  举报