poj 3026
挺直接的一个题 哎 想复杂了
题意:把n*m矩阵中的字母最小生成树 求它的边权值之和 只有字母可以分叉 多了一个提取点的过程
思路:prime 算法的简单应用
#include<iostream> #include<queue> #include<cstring> using namespace std; char map[55][55]; int node[55][55]; int edge[111][111]; int nsum; struct Node { int x,y; int t; }; int m,n; int dir[4][2]={1,0,-1,0,0,-1,0,1}; void bfs(int x,int y) { Node now,next; queue<Node> q; now.x=x,now.y=y,now.t=0; int i,j; int v[55][55]; q.push(now); for(i=0;i<n;i++) for(j=0;j<m;j++) v[i][j]=999999999; v[x][y]=0; while(!q.empty()) { now=q.front();q.pop(); if(node[now.x][now.y]) edge[node[x][y]][node[now.x][now.y]]=now.t; for(i=0;i<4;i++) { int xx=now.x+dir[i][0]; int yy=now.y+dir[i][1]; if(xx<0||xx>=n||yy<0||yy>=m) continue; if(map[xx][yy]=='#') continue; if(v[xx][yy]>now.t+1) { v[xx][yy]=now.t+1; next.x=xx; next.y=yy; next.t=now.t+1; q.push(next); } } } return ; } void prime() { int sum=0; int s[111]; memset(s,0,sizeof(s)); int dist[111]; int i,j; dist[1]=0; s[1]=1; for(i=2;i<=nsum;i++) dist[i]=edge[1][i]; dist[1]=0; for(i=1;i<=nsum;i++) { int min=99999999; int v=-1; for(j=1;j<=nsum;j++) if(!s[j]&&dist[j]<min) { min=dist[j]; v=j; } if(v==-1) break; s[v]=1; sum+=dist[v]; for(j=1;j<=nsum;j++) if(dist[j]>edge[v][j]) dist[j]=edge[v][j]; } cout<<sum<<endl; } int main() { int t,i,j; char s[100]; scanf("%d",&t); while(t--) { nsum=0; memset(node,0,sizeof(node)); scanf("%d%d",&m,&n); gets(s); for(i=0;i<n;i++) { gets(map[i]); for(j=0;j<m;j++) { if(map[i][j]=='S'||map[i][j]=='A') node[i][j]=++nsum; } } for(i=1;i<=nsum;i++) for(j=1;j<=nsum;j++) edge[i][j]=99999999; for(i=0;i<n;i++) for(j=0;j<m;j++) if(node[i][j]) bfs(i,j); prime(); } return 0; }