截至到目前为止,对图论已经看到六种算法了,第一种就是自己很理解的并查集算法,上面的题中自然有提到,第二种便是dijkstra算法,当然上面题中依然有提到的,第三种便是floyd算法,至于这个经典算法,当然也要会用点的,第四种便是接下来要说的prim算法,至于第五种的拓扑排序和krustkal算法,目前还没用过,这里暂不提;
题目链接: http://poj.org/problem?id=2395
这一题的大致就是从一个庄园到另一个庄园,在每个庄园都可以装水,求要经过所有庄园要求所带的水尽量少,求在这种尽量小的情况下拿水最多的一次,并且所有庄园都可以由1号庄园到达;
这里用了prim算法,主要代码如下:
int map[1000][1000];
int flag[1000];
int count[1000];
int x,max,min,k;
#define inf Oxffffffff
for(i=1,i<=n;i++)
{
flag[i]=0;
count[i]=map[x][i];l////x为起始庄园;
}
flag[x]=1;
count[x]=0;
for(i=1;i<=n;i++)
{
min=inf;
for(j=1;j<=n;j++)
{
if(flag==0&&count[i]<min)
{
min=count[i];
k=j;
}
}
flag[k]=1;
for(j=1;j<=n;j++)
{
if(flag[j]==0&&count[j]>map[k][j])///由于prim算法球的只是最短边,所以这里便是求最短边得地方
count[j]=map[k][j]; ////也就是从x到 j边如果比从k到j大,便用从k到j边,因为前提从x到j目前是剩下的最小的边
} ///这样一连,图是联通的
max=0;
for(j=1;j<=n;j++)
if(count[j]>max)
max=count[j];
return max:
}
#include<stdio.h> #include<string.h> #include<cstdio> #include<cstring> #define inf 0x7fffffff int map[3005][3005]; int count[3005]; int flag[3005]; int n; int prm() { int i,j,k,min,max=0; for(i=1;i<=n;i++) { flag[i]=0; count[i]=map[1][i]; } flag[1]=1; count[1]=0; for(i=1;i<=n;i++) { min=inf; for(j=1;j<=n;j++) { if(flag[j]==0&&count[j]<min) { min=count[j]; k=j; } } /*if(count[k]>max) max=count[k];*/ flag[k]=1;/// for(j=1;j<=n;j++) if(flag[j]==0&&count[j]>map[k][j]) count[j]=map[k][j]; } for(i=2;i<=n;i++) if(count[i]>max) max=count[i]; return max; } int main() { int m,i,j,x,y,len; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=inf; for(i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&len); if(map[x][y]>len) map[x][y]=len; if(map[y][x]>len) map[y][x]=len; } len=prm(); printf("%d\n",len); return 0; }