08-图7 公路村村通 (30分)
现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式:
输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。
输入样例:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
输出样例:
12
题目地址:http://pta.patest.cn/pta/test/18/exam/4/question/630
prime
#include <cstdio>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <iterator>
#include <queue>
#include <stack>
#include <functional>
using namespace std ;
#define N 1002
#define INF 1 << 30
int n , m ;
struct edge{
int v ;
int dist ;
};
vector<edge> ve[N] ;
bool vis[N] ;
int low[N] ;
int prime()
{
int i ;
for(i = 1 ; i <= n ; i++)
{
vis[i] = false ;
low[i] = INF ;
}
int newP = 1 ;
low[newP] = 0 ;
int num = 0 ;
int sum = 0 ;
while(num != n)
{
int minn = INF ;
int nextP = -1 ;
for(i = 1 ; i <= n ; i++)
{
if(!vis[i] && low[i] < minn)
{
minn = low[i] ;
nextP = i ;
}
} // for
if(nextP == -1)
return -1 ;
sum += minn ;
vis[nextP] = true ;
int len = ve[nextP].size() ;
for(i = 0 ;i < len ; i++)
{
int v = ve[nextP][i].v ;
int dist = ve[nextP][i].dist ;
if(!vis[v] && dist < low[v] )
{
low[v] = dist ;
}
}
newP = nextP ;
num ++ ;
}// while
if(num != n )
return -1 ;
return sum ;
}
int main()
{
//freopen("in.txt", "r", stdin);
scanf("%d%d",&n,&m) ;
int i ;
int u , v , dist ;
edge et ;
for(i = 0 ;i < m ; i++)
{
scanf("%d%d%d" ,&u , &v , &dist) ;
et.v = v ;
et.dist = dist;
ve[u].push_back(et) ;
et.v = u ;
ve[v].push_back(et);
}
printf("%d\n" , prime() ) ;
return 0;
}
prime解法
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
#define N 1002
#define INF 999999999
int n,m;
int mp[N][N];
int low[N];
int vis[N];
int prime()
{
int costs = 0;
int i, j;
int newP = 1;
for (i = 1; i <= n; i++)
{
low[i] = mp[newP][i];
vis[i] = false;
}
vis[newP] = true;
int num = 1;
while (num < n)
{
int minn = INF;
int tmpNewP = newP;
for (i = 1; i <= n; i++)
{
if (!vis[i] && low[i] < minn)
{
minn = low[i];
newP = i;
}
}
if (minn == INF) // 找不到这样的一点
{
return -1;
}
num++;
//costs += mp[tmpNewP][newP];
costs += low[newP]; // 这里是加上low[newP] 否则错误 , 是最小
for (i = 1; i <= n; i++)
{
if (!vis[i] && mp[newP][i] < low[i])
{
low[i] = mp[newP][i];
}
}
vis[newP] = true;
}
if (num < n)
return -1;
return costs;
}
int main()
{
//freopen("in", "r", stdin);
int i, j;
while (scanf("%d%d",&n,&m) != EOF)
{
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
mp[i][j] = INF;
mp[j][i] = INF;
}
mp[i][i] = 0;
}
int u, v, cost;
for (i = 0; i < m; i++)
{
scanf("%d%d%d", &u, &v, &cost);
mp[u][v] = cost;
mp[v][u] = cost;
}
printf("%d\n", prime());
}
//printf("\n");
return 0;
}
kruskal+并查集
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
#define N 1002
int n,m;
struct edge{
int u, v, cost;
};
vector<edge> ve;
bool cmp(edge e1, edge e2)
{
return e1.cost < e2.cost;
}
int father[N];
int find(int x)
{
if (x == father[x])
return x;
return father[x] = find(father[x]);
}
void merge(int x, int y)
{
father[find(y)] = find(x);
}
int kruskal()
{
int costs = 0;
int num = 0;
int coutNow = 0;
// n - 1条边可以加入就行了
while (num < n-1)
{
if (coutNow >= m)
{
break;
}
edge etNow = ve[coutNow++];
int u = etNow.u;
int v = etNow.v;
if (find(u) != find(v))
{
merge(u, v);
num++;
costs += etNow.cost;
}
}
if (num != n - 1)
return -1;
return costs;
}
int main()
{
//freopen("in", "r", stdin);
int i, j;
while (scanf("%d%d",&n,&m) != EOF)
{
edge et;
ve.clear();
for (i = 1; i <= n; i++)
{
father[i] = i;
}
for (i = 0; i < m; i++)
{
scanf("%d%d%d", &et.u, &et.v, &et.cost);
ve.push_back(et);
}
sort(ve.begin(), ve.end(), cmp);
printf("%d\n",kruskal());
}
//printf("\n");
return 0;
}