hdu 1879 点击打开链接
若状态为1 则将两点归并
克鲁斯卡尔 算法:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int father[110],map[110][110];
int ans,n;
struct node
{
int x,y;
int c;
} s[5100];
bool cmp(node a,node b)
{
return a.c<b.c;
}
int find(int i)
{
if(father[i]!=i)
father[i]=find(father[i]);
return father[i];
}
void merge(int a,int b)
{
a=find(a);b=find(b);
if(a>b)
father[a]=b;
else
father[b]=a;
}
void kru()
{
for(int i=0; i<n*(n-1)/2; i++)
{
int a=find(s[i].x);
int b=find(s[i].y);
a=father[a];//使得father节点都为一个节点。
b=father[b];
if(a!=b)
{
ans+=s[i].c;
merge(a,b);
}
}
}
int main()
{
int i,z,tem;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
for(i=0; i<=n; i++)
father[i]=i;
for(i=0; i<n*(n-1)/2; i++)
{
scanf("%d%d%d%d",&s[i].x,&s[i].y,&s[i].c,&z);
if(z==1)//在输入过程中即更新father数组
{
int xx=find(s[i].x);
int yy=find(s[i].y);
if(xx!=yy)
merge(xx,yy);
}
}
sort(s,s+n*(n-1)/2,cmp);
ans=0;
kru();
printf("%d\n",ans);
}
return 0;
}
prim算法:
#include<stdio.h>
#include<string.h>
int map[110][110],visit[11000],low[110];
int n,ans;
void prim()
{
int pos,i,j,min=999999;
visit[1]=1;pos=1;
for(i=1;i<=n;i++)
{
if(i!=pos)
low[i]=map[pos][i];
}
for(i=1;i<n;i++)
{
min=99999999;
for(j=1;j<=n;j++)
{
if(visit[j]!=1&&min>low[j])
{
min=low[j];
pos=j;
}
}
visit[pos]=1;
ans+=low[pos];
for(j=1;j<=n;j++)
{
if(visit[j]!=1&&map[pos][j]<low[j])
low[j]=map[pos][j];
}
}
}
int main()
{
int x,y,c,i,z;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
memset(map,0,sizeof(map));
memset(visit,0,sizeof(visit));
for(i=0;i<n*(n-1)/2;i++)
{
scanf("%d%d%d%d",&x,&y,&c,&z);
map[x][y]=map[y][x]=c;
if(z==1)
map[x][y]=map[y][x]=0;//key::不能用visit标记 否则在对low数组更新是会出问题!!!
}
ans=0;
prim();
printf("%d\n",ans);
}
return 0;
}