题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102
模板题。题意是有N个村子,给出每个村子之间的距离。有些路已经修好了,有些没有。求使每个村子都能互通马路最少还需修多少距离的路。换个说法就是求最小生成树,不过有些点或者边已经加到集合里去了。
kruskal算法:
/*
* @Author: Samson
* @Date: 2018-06-13 17:35:19
* @Last Modified by: Samson
* @Last Modified time: 2018-06-13 21:36:51
*/
// @URL : http://acm.hdu.edu.cn/showproblem.php?pid=1102
#include<bits/stdc++.h>
#include<algorithm>
#include <cstdlib>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 1e4+10;
struct node
{
int u,v,w;
}e[MAXN];
int f[110];
bool cmp(node a,node b)
{
return a.w<b.w;
}
int find(int x)
{
return x==f[x]?x:f[x] = find(f[x]);
}
int kruskal(int n,int num)
{
sort(e+1,e+1+num,cmp);
int sum = 0,cnt = 0;
for(int i = 1; i <= num; ++i)
{
int x = e[i].u,y = e[i].v;
x = find(x), y = find(y);
if(x != y)
{
sum += e[i].w;
f[y] = x;
++cnt;
}
if(cnt == n-1) break; //优化,如果所有点都已经在集合里就终止循环
}
return sum;
}
int main(void)
{
ios::sync_with_stdio(false);
//cin.tie(0);
int n;
while(cin>>n)
{
int k,cnt = 0;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
{
cin>>k;
if(i >= j) continue;
e[++cnt].u = i, e[cnt].v = j, e[cnt].w = k;
}
}
for(int i = 1; i <= n; ++i)
f[i] = i;
int q,x,y;
cin>>q;
while(q--)
{
cin>>x>>y;
x = find(x), y = find(y);
f[x] = y;
}
cout<<kruskal(n,cnt)<<'\n';
}
return 0;
}
Prim做法:
/*
* @Author: Samson
* @Date: 2018-06-13 21:37:30
* @Last Modified by: Samson
* @Last Modified time: 2018-06-13 21:59:59
*/
// @URL : http://acm.hdu.edu.cn/showproblem.php?pid=1102
#include<bits/stdc++.h>
#include<algorithm>
#include <cstdlib>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 1e4+10;
struct node
{
int u,v,w;
}e[MAXN];
int f[110],color[110],d[110],p[110],a[110][110],n;
int prim()
{
int minv,u;
d[1] = 0;
while(1)
{
minv = INF;
u = -1;
for(int i = 1; i <= n; ++i)
{
if(minv > d[i] && !color[i])
{
minv = d[i];
u = i;
}
}
if(u == -1) break;
color[u] = 1;
for(int v = 1; v <= n; ++v)
{
if(!color[v])
{
if(d[v] > a[u][v])
{
d[v] = a[u][v];
p[v] = u;
}
}
}
}
int sum = 0;
for(int i = 1; i <= n; ++i)
{
if(p[i] != -1)
sum += a[i][p[i]];
}
return sum;
}
int main(void)
{
ios::sync_with_stdio(false);
//cin.tie(0);
while(cin>>n)
{
int k,cnt = 0;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
{
cin>>a[i][j];
}
}
for(int i = 1; i <= n; ++i)
{
color[i] = 0;
p[i] = -1;
d[i] = INF;
}
int q;
cin>>q;
while(q--)
{
int u,v;
cin>>u>>v;
a[u][v] = a[v][u] = 0;
}
cout<< prim() <<'\n';
}
return 0;
}