7-10 公路村村通 (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
两个方法
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=5005;
const int maxm=200205;
int father[maxn];
int n,m;
int mst;
struct node{
int u,v,w;
bool operator<(const node & n)const{
return w<n.w;
}
}g[maxm];
int find(int x){
if(x==father[x])return x;
return father[x]=find(father[x]);//路径压缩,把递归过程中遇到的
//结点的祖宗结点也直接修改了。
}
void merge(int v,int u){
father[find(v)]=find(u);
}
bool k(){
for(int i=1;i<=n;i++){
father[i]=i;
}
int cnt;
cnt=mst=0;
sort(g,g+m);
for(int i=0;i<m;i++){
int u=g[i].u;
int v=g[i].v;
int w=g[i].w;
if(find(u)!=find(v)){
mst+=w;
cnt++;
merge(u,v);
if(cnt==n-1)return true;
}
}
return false;
}
int main(){
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>g[i].u>>g[i].v>>g[i].w;
}
if(k()){
cout<<mst<<endl;
}
else cout<<"-1"<<endl;
return 0;
}
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1100;
const int Inf=0x3f3f3f3f;
int n,m;
int adj[maxn][maxn];
int cost[maxn],vis[maxn];
int prim(){
for(int i=0;i<=n;i++){
cost[i]=Inf;
vis[i]=0;
}
cost[1]=0;
int res=0;
for(int i=1;i<=n;i++){
int minn=0;
int flag=0;
for(int j=1;j<=n;j++){
if(vis[j]==0&&cost[j]<cost[minn]){
minn=j;
flag=1;
}
}
vis[minn]=1;
res+=cost[minn];
if(flag==0)return -1;
for(int i=1;i<=n;i++){
if(!vis[i]&&cost[i]>adj[minn][i]){
cost[i]=adj[minn][i];
}
}
}
return res;
}
int main(){
cin>>n>>m;
if(m<n-1){
cout<<-1<<endl;
return 0;
}
memset(adj,0x3f,sizeof(adj));
for(int i=0;i<m;i++){
int a,b,c;
cin>>a>>b>>c;
adj[a][b]=c;
adj[b][a]=c;
}
//if(prim()==Inf)cout<<-1<<endl;
//else
cout<<prim()<<endl;
return 0;
}