hdu 1863 畅通工程(prim算法实现和kruskal算法实现)
2011-02-17 22:41
393 查看
最小生成树的prim算法,思想就是先指定一个点进入点集A(A为已处理过的点的集合),以改点为起点,扫描和该点连接的路径,取最小值计入总路径长度sum,并把该路径的另一点并入A,再以这点为起点扫描……最后得到的sum即为结果
prim的邻接阵代码:
#include <stdio.h>
#include <string.h>
#define size 105
#define INIT 999999
int count;
int Graph[size][size];
long sum;
void Prim(int villige)
{
int i,j;
int min,locate;
int dist[size];
sum=0;
bool visited[size];
memset(visited,0,sizeof(visited));
memset(dist,INIT,sizeof(dist));
for(i=1;i<=villige;i++) //默认第一个点已经进入集合
dist[i] = Graph[1][i];
count = 1;
for (j=2;j<=villige;j++)
{
min = INIT;
//找到距离已标记集合最近的点
for(i=2;i<=villige;i++)
{
if (!visited[i]&&dist[i]<min) //存在未标记的点,min的值才会改变
{
min = dist[i];
locate = i;
}
}
if(min!=INIT) //如果min值改变
{
visited[locate] = true;
sum+=min;
count++;
//dist[]的更新
for (i=1;i<=villige;i++)
{//已经标记过的点,还有自身不用考虑,然后把集合外的点到集合的最小距离存入dist[]
if(!visited[i]&&Graph[locate][i]!=0&&dist[i]>Graph[locate][i])
dist[i] = Graph[locate][i];
}
}
else return ;
}
}
int main()
{
int road,villige;
int i,j,weight;
while (scanf("%d%d",&road,&villige)!=EOF&&road)
{
count = 0;
for(i=0;i<=villige;i++)
{
for(j=0;j<=villige;j++)
if(i==j)
Graph[i][j] = 0;
else
Graph[i][j] = INIT;
}
while (road--)
{
scanf("%d%d%d",&i,&j,&weight);
Graph[i][j] = weight;
Graph[j][i] = weight;
}
Prim(villige);
if(count==villige) printf("%ld/n",sum);
else printf("?/n");
}
return 0;
}prim的邻接表代码:
#include<cstdio>
#include<cstring>
#include<climits>
const int N = 205;
struct Edge{
int s,e,v;
int next;
}edge
;
int e_num,n,m,head
,vis
,dist
;
void AddEdge(int a,int b,int c){
edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c;
edge[e_num].next=head[a]; head[a]=e_num++;
edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=c;
edge[e_num].next=head[b]; head[b]=e_num++;
}
void getmap(){
int a,b,c;
e_num=0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
while(m--){
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c);
}
}
void prim(){
int i,j,cur;
for(i=1;i<=n;dist[i++]=INT_MAX);
for(i=head[1];i!=-1;i=edge[i].next)
dist[edge[i].e]=(edge[i].v<dist[edge[i].e]?edge[i].v:dist[edge[i].e]);
vis[1]=1;
int sum=0;
int count=1;
for(i=2;i<=n;i++){
int min=INT_MAX;
for(j=1;j<=n;j++){
if(!vis[j] && dist[j]<min){
min=dist[j]; cur=j;
}
}
if(min==INT_MAX)break;
sum+=min;
vis[cur]=1;
count++;
if(count==n)break;
for(j=head[cur];j!=-1;j=edge[j].next){
int u=edge[j].e;
if(!vis[u] && dist[u]>edge[j].v)
dist[u]=edge[j].v;
}
}
count<n?printf("?\n"):printf("%d\n",sum);
}
int main()
{
while(scanf("%d%d",&m,&n),m)//m条路径,n个点
{
getmap();
prim();
}
return 0;
}
prim的邻接阵代码:
#include <stdio.h>
#include <string.h>
#define size 105
#define INIT 999999
int count;
int Graph[size][size];
long sum;
void Prim(int villige)
{
int i,j;
int min,locate;
int dist[size];
sum=0;
bool visited[size];
memset(visited,0,sizeof(visited));
memset(dist,INIT,sizeof(dist));
for(i=1;i<=villige;i++) //默认第一个点已经进入集合
dist[i] = Graph[1][i];
count = 1;
for (j=2;j<=villige;j++)
{
min = INIT;
//找到距离已标记集合最近的点
for(i=2;i<=villige;i++)
{
if (!visited[i]&&dist[i]<min) //存在未标记的点,min的值才会改变
{
min = dist[i];
locate = i;
}
}
if(min!=INIT) //如果min值改变
{
visited[locate] = true;
sum+=min;
count++;
//dist[]的更新
for (i=1;i<=villige;i++)
{//已经标记过的点,还有自身不用考虑,然后把集合外的点到集合的最小距离存入dist[]
if(!visited[i]&&Graph[locate][i]!=0&&dist[i]>Graph[locate][i])
dist[i] = Graph[locate][i];
}
}
else return ;
}
}
int main()
{
int road,villige;
int i,j,weight;
while (scanf("%d%d",&road,&villige)!=EOF&&road)
{
count = 0;
for(i=0;i<=villige;i++)
{
for(j=0;j<=villige;j++)
if(i==j)
Graph[i][j] = 0;
else
Graph[i][j] = INIT;
}
while (road--)
{
scanf("%d%d%d",&i,&j,&weight);
Graph[i][j] = weight;
Graph[j][i] = weight;
}
Prim(villige);
if(count==villige) printf("%ld/n",sum);
else printf("?/n");
}
return 0;
}prim的邻接表代码:
#include<cstdio>
#include<cstring>
#include<climits>
const int N = 205;
struct Edge{
int s,e,v;
int next;
}edge
;
int e_num,n,m,head
,vis
,dist
;
void AddEdge(int a,int b,int c){
edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c;
edge[e_num].next=head[a]; head[a]=e_num++;
edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=c;
edge[e_num].next=head[b]; head[b]=e_num++;
}
void getmap(){
int a,b,c;
e_num=0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
while(m--){
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c);
}
}
void prim(){
int i,j,cur;
for(i=1;i<=n;dist[i++]=INT_MAX);
for(i=head[1];i!=-1;i=edge[i].next)
dist[edge[i].e]=(edge[i].v<dist[edge[i].e]?edge[i].v:dist[edge[i].e]);
vis[1]=1;
int sum=0;
int count=1;
for(i=2;i<=n;i++){
int min=INT_MAX;
for(j=1;j<=n;j++){
if(!vis[j] && dist[j]<min){
min=dist[j]; cur=j;
}
}
if(min==INT_MAX)break;
sum+=min;
vis[cur]=1;
count++;
if(count==n)break;
for(j=head[cur];j!=-1;j=edge[j].next){
int u=edge[j].e;
if(!vis[u] && dist[u]>edge[j].v)
dist[u]=edge[j].v;
}
}
count<n?printf("?\n"):printf("%d\n",sum);
}
int main()
{
while(scanf("%d%d",&m,&n),m)//m条路径,n个点
{
getmap();
prim();
}
return 0;
}
kruskal算法就是并查集思想。把所有路径按权值排升序,依次取不使当前图产生回路的边,直到所有点并入集合
代码:
# include<stdio.h> # include<string.h> #include<stdlib.h> int father[101]; struct node { int from,to; int len; }path[5001]; int cmp(const void *a,const void *b) { struct node *aa=(struct node *)a; struct node *bb=(struct node *)b; return aa->len - bb->len; } int findfather(int x) { if(father[x]!=x) father[x]=findfather(father[x]); return father[x]; } void init() { int i; for(i=1;i<=100;i++) father[i]=i; } void merge(int a,int b) { int x,y; x=findfather(a); y=findfather(b); if(x!=y)father[y]=x; } int main() { int i,n,m,s,cnt; while(scanf("%d%d",&n,&m),n) { init(); for(i=0;i<n;i++) scanf("%d%d%d",&path[i].from,&path[i].to,&path[i].len); qsort(path,n,sizeof(path[0]),cmp); for(s=0,i=0;i<n;i++) { if( findfather(path[i].from) != findfather(path[i].to) ) { merge(path[i].from,path[i].to); s+=path[i].len; } } for(i=1;i<=m;i++) father[i]=findfather(i); for(cnt=0,i=1;i<=m;i++) { if(father[i]==i) cnt++; } if(cnt>1) printf("?\n"); else printf("%d\n",s); } return 0; }
相关文章推荐
- HDU 1233 还是畅通工程 最小生成树Kruskal算法和prim算法
- HDU 1863 畅通工程 Kruskal算法
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)
- hdu 畅通工程再续(最小生成树)(Prim算法 && Kruskal算法)
- hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)
- HDU 1863 畅通工程 kruskal算法 最小生成树
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)
- hdu 畅通工程再续(最小生成树)(Prim算法 && Kruskal算法)
- hdu 1863 畅通工程(kruskal算法)
- hdu1863-畅通工程 最小生成树的并查集实现方法
- HDU - 1863 - 畅通工程 (最小生成树!!prim算法!!)
- hdu--1863畅通工程2(典型的最小生成树)prim算法
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)
- hdu 畅通工程再续(最小生成树)(Prim算法 && Kruskal算法)
- HDU 1863 畅通工程(Kruskal算法)
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)
- hdu 畅通工程再续(最小生成树)(Prim算法 && Kruskal算法)
- HDU 1863 畅通工程(最小生成树prim算法)
- HDU 1863 畅通工程(Prim算法求解MST)
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)