1348:【例4-9】城市公交網建設問題
時間限制: 1000 ms 內存限制: 65536 KB
【題目描述】
有一張城市地圖,圖中的頂點爲城市,無向邊代表兩個城市間的連通關係,邊上的權爲在這兩個城市之間修建高速公路的造價,研究後發現,這個地圖有一個特點,即任一對城市都是連通的。現在的問題是,要修建若干高速公路把所有城市聯繫起來,問如何設計可使得工程的總造價最少?
【輸入】
n(城市數,1<≤n≤100)
e(邊數)
以下e行,每行3個數i,j,wij,表示在城市i,j之間修建高速公路的造價。
【輸出】
n-1行,每行爲兩個城市的序號,表明這兩個城市間建一條高速公路。
【輸入樣例】
5 8
1 2 2
2 5 9
5 4 7
4 1 10
1 3 12
4 3 6
5 3 3
2 3 8
【輸出樣例】
1 2
2 3
3 4
3 5
思路:這題就是輸出倆個城市之間的路,這裏我們用kruskal,輸入數據的時候要保證小的在前,是爲了輸出做準備的,這對題目是沒有影響的因爲並查集就是相當於無向圖。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 105;//最大點數
const int M = 10000;//最大邊數
int f[N];//並查集函數
int cnt;//邊數
struct node{
int u;
int v;
int w;
}edge[M];//邊存儲內容,頂點 邊 權值
void addedge(int u,int v, int w){//加邊
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt++].w = w;
}
bool cmp(node a, node b){//排序函數
return a.w < b.w;
}
int find(int x){//並查集
if(f[x] == -1)
return x;
else
return f[x] = find(f[x]);
}
int kruskal(int n)//傳入點數,返回最小生成樹的權值,如果不連通返回-1
{
memset(f,-1,sizeof(f));
sort(edge,edge+cnt,cmp);
int sum = 0;//加入的邊數
int ans = 0;//權值的和
for(int i = 0 ; i <= cnt; i++)
{
int u = edge[i].u;
int v = edge[i].v;
int w = edge[i].w;
int t1 = find(u);
int t2 = find(v);
if(t1 != t2)
{
ans += w;
f[t1] = t2;
cout << u <<" "<<v << endl;
sum++;
}
if(cnt == n-1)
break;
}
if(sum < n - 1)//不聯通
return -1;
else
return ans;
}
int main(){
int n,m;
cin >> n >> m;
cnt = 0;
for(int i = 0; i < m; i++)
{
int a,b,c;
cin >> a >> b >> c;
addedge(a,b,c);
}
kruskal(n);
return 0;
}