P1223 [小数据版]边权差值最小的生成树

  这道题和最小生成树kruskal的代码几乎相同,只不过不一定是最小生成树,所以不一定从最短的边开始做生成树;所以将每一条边分别作为起点,然后枚举就行了......

  

#include 

using namespace std;

#define INF 0x3f3f3f3f

inline int read()
{
    int x = 0,ff = 1;char ch = getchar();
    while(!isdigit(ch))
    {
        if(ch == '-') ff = -1;
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = (x<<1) + (x<<3) + (ch ^ 48);
        ch = getchar();
    }
    return x * ff;
}

inline void write(int x)
{
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

struct node
{
    int x,y,v;
}e[100000];
int a,b,x,y,v,m = 0,fa[100000],mi = INF;

inline bool cmp(node x,node y)
{
    return x.v < y.v;
}

int get(int x)
{
    return (x == fa[x]) ? x : (fa[x] =  get(fa[x]));
}

int Kruskal(int ans)
{
    int maxx = -1,minn = INF;
    for(int i = 1;i <= a;++i)
    fa[i] = i;
    int sum = 0,cnt = 0;
    sort(e + 1,e + m + 1,cmp);
    for(int i = ans;cnt < a - 1;++i)
    {
        ++sum;
        if(sum > m) return -1; // 所有的边都找过,不能构成树; 
        int x = get(e[i % m].x),y = get(e[i % m].y); // i可能大于m,所以用i % m; 
        if(x != y)
        {
            ++cnt;
            fa[x] = y;
            maxx = max(maxx,e[i % m].v);
            minn = min(minn,e[i % m].v);
        }
    }
    return maxx - minn;
}

int main()
{
    a = read(); b = read();
    for(int i = 1;i <= b;++i)
    {
        x = read(); y = read(); v = read();
        e[++m].x = x; e[m].y = y; e[m].v = v;
    }
    for(int i = 1;i <= m;++i)
        mi = min(mi,Kruskal(i)); // 枚举不同的起点 
    write(mi);
    return 0;
}

 

转载于:https://www.cnblogs.com/AK-ls/p/10208086.html

你可能感兴趣的:(P1223 [小数据版]边权差值最小的生成树)