poj3206(bfs+最小生成树)

传送门:Borg Maze

题意:有一个迷宫,里面有一些外星人,外星人用字母A表示,#表示墙,不能走,空格可以走,从S点出发,在起点S和A处可以分叉走,问找到所有的外星人的最短路径是多少?

分析:分别bfs由S和所有A出发到其他点的距离,然后建好图进行最小生成树处理即可。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 110
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
struct edge
{
    int u,v,w;
    edge() {}
    edge(int u,int v,int w):u(u),v(v),w(w){}
    bool operator<(const edge &a)const
    {
        return w<a.w;
    }
} e[N*N];
struct node
{
    int x,y,step;
    node(){}
    node(int x,int y,int step):x(x),y(y),step(step){}
};
int fa[N],tot,total;
char str[N][N];
int num[N][N],vis[N][N],n,m;
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int MST(int n)
{
    int ans=0;
    for(int i=1;i<=n;i++)fa[i]=i;
    sort(e,e+tot);
    for(int i=0; i<tot; i++)
    {
        int a=find(e[i].u);
        int b=find(e[i].v);
        if(a==b)continue;
        fa[a]=b;
        ans+=e[i].w;
    }
    return ans;
}
bool judge(int a,int b)
{
    return a>=1&&a<=n&&b>=1&&b<=m&&str[a][b]!='#'&&!vis[a][b];
}
void bfs(int x,int y)
{
    queue<node>que;
    while(!que.empty())que.pop();
    FILL(vis,0);
    vis[x][y]=1;
    que.push(node(x,y,0));
    while(!que.empty())
    {
        node now=que.front();que.pop();
        for(int i=-1;i<=1;i++)
        for(int j=-1;j<=1;j++)
        {
            if(i+j==0||i==j)continue;
            int a=now.x+i,b=now.y+j,step=now.step+1;
            if(judge(a,b))
            {
                if(str[a][b]=='A'||str[a][b]=='S')
                {
                    e[tot++]=edge(num[x][y],num[a][b],step);
                }
                vis[a][b]=1;
                que.push(node(a,b,step));
            }
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&m,&n);
        gets(str[0]);
        for(int i=1;i<=n;i++)
            gets(str[i]);
        total=0;tot=0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(str[i][j]=='A'||str[i][j]=='S')
            {
                num[i][j]=++total;
            }
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(str[i][j]=='A'||str[i][j]=='S')
            {
                bfs(i,j);
            }
        }
        printf("%d
",MST(total));
    }
}
View Code
原文地址:https://www.cnblogs.com/lienus/p/4277983.html