CF 436D 最小生成树
设一个开头的虚节点,然后建稠密图,O(n^2)。使用prim。O(n^2),保存方案,没什么好说的。
#include <string.h> #include <stdio.h> #include <algorithm> #include <vector> using namespace std; int k,w,n,m; int cnt; int map[1005][1005]; char data[1002][11][11]; int father[1005]; struct node { int pre,to; }save[1005]; int prim() { int ans=0; int i,j; int vis[1005]; int dis[1005]; memset(vis,0,sizeof(vis)); memset(dis,0x7f,sizeof(dis)); int inf=dis[0]; vis[0]=1; int min; for (i=1;i<=k;i++) { dis[i]=map[0][i]; father[i]=0; } int u; for (i=0;i<k;i++) { min=inf; for (j=0;j<=k;j++) if (!vis[j] && min>dis[j]) { u=j; min=dis[j]; } vis[u]=1; ans+=dis[u]; save[cnt].pre=u;save[cnt].to=father[u]; cnt++; for (int p=0;p<=k;p++) if (u!=p && !vis[p]) if (dis[p]>map[u][p]) { dis[p]=map[u][p]; father[p]=u; } } return ans; } int main() { int i; while (scanf("%d%d%d%d",&n,&m,&k,&w)!=EOF) { cnt=0; for (i=1;i<=k;i++) { for (int j=0;j<n;j++) scanf("%s",data[i][j]); } for (i=1;i<=k;i++) { map[0][i]=n*m; map[i][0]=m*n; } int tmp; for (i=1;i<=k;i++) { for (int j=i+1;j<=k;j++) { tmp=0; for (int p=0;p<n;p++) for (int q=0;q<m;q++) if (data[i][p][q]!=data[j][p][q]) tmp+=w; map[i][j]=tmp; map[j][i]=tmp; } } printf("%d\n",prim()); for (i=0;i<cnt;i++) printf("%d %d\n",save[i].pre,save[i].to); } return 0; }