nyoj 38 http://acm.nyist.net/JudgeOnline/problem.php?pid=38
prim 克鲁斯卡尔 两个算法
首先说说 克鲁斯卡尔算法,按照边的从小到大排序之后,利用并查集的思想,不断并。直到并出n-1条边。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
typedef long long int LL;
const int INF=2e9+1e8;
const double eps=1e-8;
const int MM=500+5;
struct Edge
{
int s,t,val;
};
Edge edge[MM*MM/2];
int m,n;
int pre[MM];
void init_pre()
{
for(int i=0; i<=n; i++)
pre[i]=i;
}
bool cmp(Edge a,Edge b)
{
return a.val<b.val;
}
int getfa(int x)
{
return pre[x]==x?x:pre[x]=getfa(pre[x]);
}
bool merges(int x,int y)
{
int fx=getfa(x),fy=getfa(y);
if(fx==fy) return false;
else
{
pre[fx]=fy;
return true;
}
}
int Kruskal()
{
sort(edge+1,edge+1+m,cmp);
int tot=0;
for(int i=1; i<=m; i++)
{
if(merges(edge[i].s,edge[i].t))
{
tot+=edge[i].val;
}
}
return tot;
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d%d",&n,&m);
init_pre();
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&edge[i].s,&edge[i].t,&edge[i].val);
}
int minn=INF;
for(int i=1; i<=n; i++)
{
int temp;
scanf("%d",&temp);
minn=min(temp,minn);
}
printf("%d\n",Kruskal()+minn);
}
return 0;
}
prim
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:V
new = {x},其中x为集合V中的任一节点(起始点),E
new = {},为空;
3).重复下列操作,直到V
new = V:
b.将v加入集合V
new中,将<u, v>边加入集合E
new中;
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn=505;
const int INF=0x3f3f3f3f;
int map[maxn][maxn];
int dis[maxn];
int vis[maxn];
int N;//N组测试数据
int V;//点的数量
int E;//边的数量
int min_num;//最小外接花费
void init()
{
scanf("%d%d",&V,&E);
for(int i=0; i<=V; i++)//初始化图
for(int j=0; j<=V; j++)
i==j?map[i][j]=0:map[i][j]=INF;
while(E--)//建图
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
map[a][b]=c;//无向图
map[b][a]=c;
}
min_num=INF;
for(int i=1; i<=V; i++)
{
int x;
scanf("%d",&x);
min_num=min(min_num,x);//生成树连接到外界的最小花费
dis[i]=map[i][1];//从1开始构造最小生成树
}
memset(vis,0,sizeof(vis));
vis[1]=1;//0代表是外界
}
void Prim()
{
int min_cost=0;//初始化最小花费
for(int i=1; i<V; i++)
{
int minn=INF;
int point_minn;
for(int j=1; j<=V; j++)
if(vis[j]==0&&minn>dis[j])
{
point_minn=j;
minn=dis[j];
}
if(minn==INF)
break;
min_cost+=dis[point_minn];
vis[point_minn]=1;
for(int j=1; j<=V; j++)
if(vis[j]==0&&dis[j]>map[point_minn][j])
dis[j]=map[point_minn][j];
}
printf("%d\n",min_cost+min_num);
}
int main()
{
scanf("%d",&N);
while(N--)
{
init();
Prim();
}
return 0;
}