Description
问题描述:链接
思路
题目很直接,容易看出建的图是一张完全图,需要求出图中最小生成树的最大边权。由于数据上界已经定死了,那么选择用静态邻接表存建图。由于图是稠密图,那么求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; }