1. 程式人生 > >洛谷 P1546 最短網絡 Agri-Net(最小生成樹)

洛谷 P1546 最短網絡 Agri-Net(最小生成樹)

pre div spa 鏈接 namespace tdi 我們 nbsp 個數字

嗯...

題目鏈接:https://www.luogu.org/problemnew/show/P1546

首先不難看出這道題的思想是用了最小生成樹,但是這道題有難點:

1.讀題讀不明白

2.不會讀入

3.跑多了

針對1:

首先這道題和其他題一樣,你所讀入的矩陣中的每一個數字都代表著相鄰兩點之間的邊的邊權,而這個點所處的位置即可以用(i,j)來表示,然後再進行操作即可

針對2:

我們會發現這個N*N的矩陣是關於對角線對稱的,所以我們只需要讀上面一部分或者下面一部分即可(要讀上面一部分讀入時則特判j>i,相反則特判j<i...

針對3:

這裏就用到了生成樹的性質:n個點,n-1條邊,所以在合並的時候我們定義一個k,存儲合並後邊的條數,每合並一次則加一,最後當k == n-1時則跳出即可

AC代碼:

技術分享圖片
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 int cnt, f[1005];
 7 
 8 int k, h;
 9 struct node{
10     int x, y, l;
11 } a[110005];
12 
13 inline int cmp(node i, node j){
14     return i.l < j.l;
15 }
16
17 inline int find(int x){ 18 if(f[x] != x) 19 f[x] = find(f[x]); 20 return f[x]; 21 } 22 23 int main(){ 24 int n; 25 int z; 26 scanf("%d", &n); 27 for(int i = 1; i <= n; i++){ 28 for(int j = 1; j <= n; j++){ 29 scanf("%d", &z);
30 if(j > i){ //只讀取上面一半有用的數據 31 a[++cnt].x = i; 32 a[cnt].y = j; 33 a[cnt].l = z; 34 } 35 } 36 } 37 for(int i = 1; i <= n; i++) 38 f[i] = i; 39 sort(a+1, a+cnt+1, cmp); 40 for(int i = 1; i <= cnt; i++){ 41 int r1 = find(a[i].x); 42 int r2 = find(a[i].y); 43 if(r1 != r2){ 44 f[r1] = r2; 45 h += a[i].l; 46 k++; 47 } 48 if(k == n-1) break;//跳出 49 } 50 printf("%d", h); 51 return 0; 52 }
AC代碼

洛谷 P1546 最短網絡 Agri-Net(最小生成樹)