POJ1797 Heavy Transportation (最短路径/最小生成树kruskal)

本文出自:http://blog.csdn.net/svitter

原题连接:http://poj.org/problem?id=1797


题意:找出一条从1 ~ n的所有的路径中权值最小的那条路径,然后找出其中权值最大的边。

看了吉大的指导才用最小生成树的心态去做,其实压根没读明白题目。。这个题目可以用最小生成树的心态去解,因为是找最短的路径。krus中灵活运用了并查集的思想,所以在这里面,如果1, n在同一个集合中,也就找到了最短的路径,然后因为按照边的长短依此加入的,因此,使find(1) == find(n)成立加入的最后一条边,即为所求。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

int p[1005];//集合的数组
int r[1005];//按秩


int m, n;
//
int find(int v)
{
    if(v != p[v])
        p[v] = find(p[v]);
    return p[v];
}

void join(int u, int v)
{
    int a = find(u);
    int b = find(v);
    if(a == b)
        return;
    if(r[a] < r[b])
    {
        p[a] = b;
    }
    else if(r[a] > r[b])
    {
        p[b] = a;
    }
    else
    {
        p[a] = b;
        r[b] ++;
    }
}

void init_set()
{
    int i;
    for(i = 1; i <= n; i++)
    {
        p[i] = i;
        r[i] = 1;
    }
}


struct Edge
{
    int u;
    int v;
    int weight;
};

struct Edge edge[1000005];

void quick_sort(struct Edge * start, struct Edge * end)
{
    if(start >= end)
        return;
    struct Edge* loc = start;
    struct Edge* iterator;
    struct Edge tmp;
    for(iterator = start; iterator != end; iterator++)
    {
        if(iterator -> weight < (end - 1) -> weight) //按从小到大的顺序排列, 决定是最小还是
        {
            tmp = *loc;
            *loc = *iterator;
            *iterator = tmp;

            loc++;
        }
    }
    tmp = *loc;
    *loc = *(end - 1);
    *(end - 1) = tmp;

    quick_sort(start, loc);
    quick_sort(loc + 1, end);
}

bool cmp(Edge e1, Edge e2)
{
    return e1.weight > e2.weight;
}

int kru()
{
    init_set();
    //quick_sort(edge, edge+m);
    sort(edge, edge + m, cmp);
    int i;
    for(i = 0; i < m; i++)
    {
        int u = edge[i].u;
        int v = edge[i].v;
        //如果两个顶点不在一个集合中,则不会生成环,于是该边被加入生成树
        if(find(u) != find(v))
        {
            join(u, v);
        }
        if(find(1) == find(n))
        {
            return edge[i].weight;
        }
    }
    return edge[i].weight;
}



void ace()
{
    int Case, no = 1;
    int ret, i;
    //freopen("test.txt", "r", stdin);
    scanf("%d", &Case);
    for(no = 1; no <= Case; no++)
    {
        scanf("%d%d", &n, &m);
        for(i = 0; i < m; i++)
        {
            scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].weight);
        }
        ret = kru();
        printf("Scenario #%d:\n%d\n\n", no, ret);
    }
}


int main()
{
    ace();
    return 0;
}



你可能感兴趣的:(C++,c,ACM,图论,kruskal)