POJ #2485 Highways MST中的最大边权

Description


 

The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public highways. So the traffic is difficult in Flatopia. The Flatopian government is aware of this problem. They're planning to build some highways so that it will be possible to drive between any pair of towns without leaving the highway system. 


Flatopian towns are numbered from 1 to N. Each highway connects exactly two towns. All highways follow straight lines. All highways can be used in both directions. Highways can freely cross each other, but a driver can only switch between highways at a town that is located at the end of both highways. 

The Flatopian government wants to minimize the length of the longest highway to be built. However, they want to guarantee that every town is highway-reachable from every other town.

Input

The first line of input is an integer T, which tells how many test cases followed. 
The first line of each case is an integer N (3 <= N <= 500), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 65536]) between village i and village j. There is an empty line after each test case.

Output

For each test case, you should output a line contains an integer, which is the length of the longest road to be built such that all the villages are connected, and this value is minimum.

Sample Input

1

3
0 990 692
990 0 179
692 179 0

Sample Output

692

Hint

Huge input,scanf is recommended.

 

思路


 

  题目很直接,容易看出建的图是一张完全图,需要求出图中最小生成树的最大边权。由于数据上界已经定死了,那么选择用静态邻接表存建图。由于图是稠密图,那么求MST的话就选择 prim 。

  做完 POJ #2253 Frogger 变种Dijkstra 后再做这个就很有感觉了。其实prim中的核心操作就是记录并更新点v到树的最短距离,然后把所有最短距离之中的最小值选出,将该点其加入树集。这个树集与dijkstra中的点集是异曲同工的。

  能用 scanf 的话尽量用 scanf 吧,比 cin 快很多。

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
const int MAXN = 510;
const int EDGE_MAXN = 250010;
int n;
//链式前向星
struct Edge {
    int to;
    int w; //2^31-1 > 65536
    int next;
}e[EDGE_MAXN];
int head[MAXN], cnt;

void addEdge (int u, int v, int w) {
    cnt++;
    e[cnt].to = v;
    e[cnt].w = w;
    e[cnt].next = head[u];
    head[u] = cnt;
}

void initG() {
    memset(head, -1, sizeof(head));
    cnt = 0;
    scanf ("%d", &n);
    for (int i = 1; i <= n; i++) {
        int tmp;
        for (int j = 1; j <= i-1; j++) {
            scanf ("%d", &tmp);
            addEdge(i, j , tmp);
        }
        scanf ("%d", &tmp); // i = j 形成自环,对建图并没有用
        for (int j = i+1; j <= n; j++) {
            scanf ("%d", &tmp);
            addEdge(i, j, tmp);
        }
    }
}

//求最小生成树的最大边权
struct Node{
    int id;
    int key;
    Node(int v, int w) : id(v), key(w) {}
    friend bool operator < (const Node& a, const Node& b) {
        return a.key > b.key;
    }
};
int d[MAXN]; //v到树的最短距离估计值
int vis[MAXN];
void prim (const int& s, int& max) {
    for (int i = 1; i <= n; i++) d[i] = INF, vis[i] = false;
    d[s] = 0;
    priority_queue <Node> pq;
    pq.push(Node(s, d[s]));
    while (!pq.empty()) {
        int u = pq.top().id; pq.pop();
        if (vis[u]) continue;
        vis[u] = true;
        if (max < d[u]) max = d[u];
        for (int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].to;
            if (!vis[v] && d[v] > e[i].w) {
                d[v] = e[i].w; //更新v到树的最短距离
                pq.push (Node(v, d[v]));
            }
        }
    }
}

int main(void) {
    int case_num;
    cin >> case_num;
    while (case_num--) {
        initG();
        int ans = 0;
        prim(1, ans);
        printf ("%d\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2018-02-24 19:19  bw98  阅读(190)  评论(0编辑  收藏  举报