Constructing RoadsTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 28385 Accepted Submission(s): 10808 Problem Description There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected.
Input The first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j.
Output You should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum.
Sample Input 3 0 990 692 990 0 179 692 179 0 1 1 2
Sample Output 179
Source
|
这条路不好修啊!几乎修了一下午了,
普利姆算法:
他给出了已修好的路,这个就让 已通路的村庄 的代价为0,就好了,
#include<iostream>
#include<string.h>
#include<cstdio>
#include<algorithm>
using namespace std;
int map[101][101],low[101],visit[101];
int Pri(int n)
{
int i,j,sum=0,pos;
for(i=1;i<=n;i++)
{
low[i]=map[1][i];
}
visit[1]=1;
for(i=1;i<n;i++)
{
int min=0x3f3f3f3f;
for(j=1;j<=n;j++)
{
if(!visit[j]&&min>low[j])
{
min=low[j];
pos=j;
//cout<<j<<" "<<min<<endl;
}
}
sum+=min;
visit[pos]=1;
for(j=1;j<=n;j++)
if(!visit[j]&&low[j]>map[pos][j])
low[j]=map[pos][j];
}
return sum;
}
int main()
{
int n,i,j,t,x,y;
while(~scanf("%d",&n))
{
memset(visit,0,sizeof(visit));
memset(map,0x3f3f3f3f,sizeof(map));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
cin>>map[i][j];
}
cin>>t;
while(t--)
{
cin>>x>>y;
map[x][y]=0;
map[y][x]=0;
}
cout<<Pri(n)<<endl;
}
return 0;
}
克鲁斯卡尔算法:
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
int a[101];
struct kk
{
int s,e,w;
};
kk s[10005];
int cmp(kk x,kk y)
{
return x.w<y.w;
}
int find(int x)
{
if(x==a[x])
return x;
else
return a[x]=find(a[x]);
}
int main()
{
int n;
int i,j,k=0,t,f=0,sum=0,m;
int fx,fy;
//freopen("1.txt","r",stdin);
while(~scanf("%d",&n))
{
k=0;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
cin>>s[k].w;
s[k].s=i;
s[k].e=j;
k++;
}
sort(s,s+k,cmp);
for(i=1; i<=n; i++)
{
a[i]=i;
}
cin>>t;
for(i=0; i<t; i++)
{
cin>>m>>j;
fx=find(m); 已通路问题:谨慎起见,先让他查找一下,若不相等,则随意让一个连通分量等于另一个连通分量或是查找的结果
fy=find(j);
if(fx!=fy)
a[fx]=a[fy];
}
sum=0;
for(i=0; i<k; i++)
{
if(s[i].w>0)
{
fx=find(s[i].s);
fy=find(s[i].e);
if(fx!=fy)
{
sum+=s[i].w;
a[fx]=a[fy];
}
}
}
cout<<sum<<endl;
}
return 0;
}