poj3026 bfs+prim

题意:

有一个n*m的图,有S,A,#和空格,S可以到达A并且使A变成S,然后这个S又可以去侵染别的A,问A都变成S需要多少步?

分析:

题目相当于求出S和A构成的最小生成树。首先把S和A找出来,枚举每个S和A,然后bfs求一下单点到其他点的最短距离,然后套prim模板就行。

这题有个特别坑的地方就是数字后面可等有多个空格,好坑!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define mp make_pair
const int INF=1000000000;
const int N=500+9;
typedef pair<int,int>pii; //点的坐标 <x,y>
typedef pair<int,pii>piii; //<步数,点>
int w[N][N],low[N];
bool vis[N][N];
char s[N][N];
int n,m;
int dx[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
vector<pii>vec; //存S和A
map<pii,int>id; //给每个S和A编一个号
int sid;
void bfs(pii start)
{
    queue<piii>q;
    memset(vis,0,sizeof(vis));
    q.push(mp(0,start));
    vis[start.first][start.second]=1;
    while(!q.empty()){
        piii p=q.front();q.pop();
        int step=p.first,x=p.second.first,y=p.second.second;
        for(int i=0;i<4;i++){
            int xx=x+dx[i][0],yy=y+dx[i][1];
            if(xx<0||yy<0||xx==n||yy==m||vis[xx][yy])continue;
            vis[xx][yy]=1;
            if(s[xx][yy]=='A'||s[xx][yy]=='S'){
                w[id[mp(xx,yy)]][sid]=step+1;continue;
            }
            if(s[xx][yy]==' ')q.push(mp(step+1,mp(xx,yy)));
        }
    }
}
int prim(int n)
{
    bool vis[111];
    memset(vis,0,sizeof(vis));
    vis[0]=1;
    int ans=0,p=0;
    for(int i=0;i<n;i++)low[i]=w[p][i];
    for(int i=1;i<n;i++){
        int minn=INF;
        for(int j=0;j<n;j++)if(!vis[j]&&minn>low[j])minn=low[p=j];
        ans+=minn;
        vis[p]=1;
        for(int j=0;j<n;j++)if(!vis[j]&&low[j]>w[p][j])low[j]=w[p][j];
    }
    return ans;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&m,&n);
        vec.clear();
        id.clear();
        gets(s[0]); //注意可能有多个空格
        for(int i=0;i<n;i++){
            gets(s[i]);
            for(int j=0;j<m;j++)
                if(s[i][j]=='A'||s[i][j]=='S')id[mp(i,j)]=vec.size(),vec.push_back(mp(i,j));
        }
  
        for(int i=0;i<vec.size();i++)for(int j=0;j<vec.size();j++)w[i][j]=i==j?0:INF;
        for(int i=0;i<vec.size();i++){
            sid=id[vec[i]];
            bfs(vec[i]);
        }
        printf("%d\n",prim(vec.size()));
    }
    return 0;
}


posted @ 2016-07-07 15:37  HARD_UNDERSTAND  阅读(143)  评论(0编辑  收藏  举报