最小生成樹的簡單變型,當然是用kruskal的,先將已經有路連起來的村莊合併成一棵樹,並將這些邊標記掉。然後將所有邊排序,判斷該邊是否被用過,根據邊從小到大合併樹,直到最後只剩一棵樹。
note:對結構體排序還不太熟。
下面是題目:
Constructing Roads
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 19069 | Accepted: 7905 |
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.
We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.
We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.
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.
Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.
Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.
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
PKU Monthly,kicc
代碼:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define range 110
#define range2 5010
struct tree{
int u,v,w;
}tr[range2];
int g[range][range],visit[range][range],deep[range],pa[range];
int find_pa(int k)
{
if(pa[k]==0) return k;
pa[k]=find_pa(pa[k]);
return pa[k];
}
void make_union(int fa,int fb)
{
// int fa=find_pa(a);
// int fb=find_pa(b);
if(fa==fb) return;
if(deep[fa]<=deep[fb])
{
pa[fa]=fb;
if(deep[fa]==deep[fb])
deep[fb]++;
}
else pa[fb]=fa;
}
bool cmp(const tree &x,const tree &y)
{
return x.w<y.w;
}
int main()
{
freopen("in.txt","r",stdin);
int n,m,i,j,sum;
scanf("%d",&n);
int num=n;
memset(pa,0,sizeof(pa));
memset(deep,0,sizeof(deep));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&g[i][j]);
scanf("%d",&m);
for(i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
int fa=find_pa(u);
int fb=find_pa(v);
if(fa!=fb)
{
make_union(fa,fb);
visit[u][v]=1;
visit[v][u]=1;
num--;
}
}
int k=0;
for(i=1;i<=n;i++)
for(j=1;j<i;j++)
{
tr[k].w=g[i][j];
tr[k].u=i;
tr[k].v=j;
k++;
}
sort(tr,tr+k,cmp);
sum=0;
// printf("k=%d\n",k);
for(i=0;i<k;i++)
{
// printf("w=%d\n",tr[i].w);
if(num==1) break;
int u=tr[i].u;
int v=tr[i].v;
if(!visit[u][v])
{
int fa=find_pa(u);
int fb=find_pa(v);
if(fa!=fb)
{
make_union(fa,fb);
sum+=tr[i].w;
visit[u][v]=1;
visit[v][u]=1;
num--;
}
}
}
printf("%d\n",sum);
return 0;
}