1、由于有了昨天写Dijkstra的经验,这次凭着理解就直接写出了求MST的Prim算法。。。
/*
ID:mrxy564
PROG:agrinet
LANG:C++
*/
#include<cstdio>
#include<cstring>
using namespace std;
const int INF=~0U>>2;
int main(){
freopen("agrinet.in","r",stdin);
freopen("agrinet.out","w",stdout);
int n,d[110],G[110][110],vis[110],ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&G[i][j]);
for(int i=0;i<n;i++)
d[i]=(i==0)?0:INF;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++){
int m=INF,x;
for(int y=0;y<n;y++)
if(!vis[y]&&d[y]<m) m=d[x=y];
ans+=m;
vis[x]=1;
for(int y=0;y<n;y++)
if(!vis[y]&&d[y]>G[x][y]) d[y]=G[x][y];
}
printf("%d\n",ans);
return 0;
}
官方题解:
This problem requires finding the minimum spanning tree of the given graph. We use an algorithm that, at each step, looks to add to the spanning tree the closest node not already in the tree.
Since the tree sizes are small enough, we don't need any complicated data structures: we just consider every node each time.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #define MAXFARM 100 int nfarm; int dist[MAXFARM][MAXFARM]; int isconn[MAXFARM]; void main(void) { FILE *fin, *fout; int i, j, nfarm, nnode, mindist, minnode, total; fin = fopen("agrinet.in", "r"); fout = fopen("agrinet.out", "w"); assert(fin != NULL && fout != NULL); fscanf(fin, "%d", &nfarm); for(i=0; i<nfarm; i++) for(j=0; j<nfarm; j++) fscanf(fin, "%d", &dist[i][j]); total = 0; isconn[0] = 1; nnode = 1; for(isconn[0]=1, nnode=1; nnode < nfarm; nnode++) { mindist = 0; for(i=0; i<nfarm; i++) for(j=0; j<nfarm; j++) { if(dist[i][j] && isconn[i] && !isconn[j]) { if(mindist == 0 || dist[i][j] < mindist) { mindist = dist[i][j]; minnode = j; } } } assert(mindist != 0); isconn[minnode] = 1; total += mindist; } fprintf(fout, "%d\n", total); exit(0); }
Here is additional analysis from Alex Schwendner:
The solution given is O(N3); however, we can obtain O(N2) if we modify it by storing the distance from each node outside of the tree to the tree in an array, instead of recalculating it each time. Thus, instead of checking the distance from every node in the tree to every node outside of the tree each time that we add a node to the tree, we simply check the value in the array for each node outside of the tree.
#include <fstream.h> #include <assert.h> const int BIG = 20000000; int n; int dist[1000][1000]; int distToTree[1000]; bool inTree[1000]; main () { ifstream filein ("agrinet.in"); filein >> n; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { filein >> dist[i][j]; } distToTree[i] = BIG; inTree[i] = false; } filein.close (); int cost = 0; distToTree[0] = 0; for (int i = 0; i < n; ++i) { int best = -1; for (int j = 0; j < n; ++j) { if (!inTree[j]) { if (best == -1 || distToTree[best] > distToTree[j]) { best = j; } } } assert (best != -1); assert (!inTree[best]); assert (distToTree[best] < BIG); inTree[best] = true; cost += distToTree[best]; distToTree[best] = 0; for (int j = 0; j < n; ++j) { if (distToTree[j] > dist[best][j]) { distToTree[j] = dist[best][j]; assert (!inTree[j]); } } } ofstream fileout ("agrinet.out"); fileout << cost << endl; fileout.close (); exit (0); }