http://acm.hust.edu.cn/vjudge/contest/121380#problem/I

 

 

题意:求有字母的各个点都彼此连接起来的最短步数。

 

分析:一看到题就想到BFS+最小生成树了, 可是我一开始不知道怎么表示,也没看穿题(还是渣渣啊。。)

 

**************************************************************************************************************************************

根据题意的“分离”规则,重复走过的路不再计算

因此当使用prim算法求L的长度时,根据算法的特征恰好不用考虑这个问题(源点合并很好地解决了这个问题),L就是最少生成树的总权值W

 

由于使用prim算法求在最小生成树,因此无论哪个点做起点都是一样的,(通常选取第一个点),因此起点不是S也没有关系

所以所有的A和S都可以一视同仁,看成一模一样的顶点就可以了

 

 

#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

const int maxn = 105;
const int oo = 0xfffffff;

int  dir[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };
char maps[maxn][maxn];
int v[maxn][maxn], dist[maxn], a[maxn][maxn], p[maxn][maxn], vis[maxn];
int n, m;

struct node
{
    int x, y, step;
};

void BFS(int u, int x, int y)
{
    memset(v, 0, sizeof(v));

    node begins, now, next;
    begins.x = x;
    begins.y = y;
    begins.step = 0;

    queue<node>Q;
    Q.push(begins);
    v[x][y] = 1;

    while(Q.size())
    {
        now = Q.front();
        Q.pop();

        if(maps[now.x][now.y]>='A' && maps[now.x][now.y] <='Z')
            p[u][a[now.x][now.y]] = now.step;

        for(int i=0; i<4; i++)
        {
            next.x = now.x + dir[i][0];
            next.y = now.y + dir[i][1];

            if(next.x>0 && next.x<=m && next.y>0 && next.y<=n && maps[next.x][next.y]!='#' && !v[next.x][next.y])
            {
                v[next.x][next.y] = 1;
                next.step = now.step + 1;
                Q.push(next);
            }
        }
    }

}

void Prim(int k)
{
    memset(vis, 0, sizeof(vis));

    int sum = 0;

    for(int i=1; i<=k; i++)
        dist[i] = p[1][i];

        vis[1] = 1;

    for(int i=1; i<k; i++)
    {
        int index = -1;
        int mins = oo;

        for(int j=1; j<=k; j++)
        {
            if(!vis[j] && dist[j]<mins)
            {
                mins = dist[j];
                index = j;
            }
        }

        sum += mins;
        vis[index] = 1;

        for(int j=1; j<=k; j++)
        {
            if(!vis[j] && dist[j] > p[index][j])
                dist[j] = p[index][j];
        }
    }

    printf("%d\n", sum);
}


int main()
{
    int T;

    scanf("%d", &T);

    while(T --)
    {
        int k = 1;

        scanf("%d %d ", &n, &m);

        for(int i=1; i<=m; i++)
        {
            gets(maps[i]);
            for(int j=1; j<=n; j++)
            {

                if(maps[i][j]=='A' || maps[i][j]=='S')
                    a[i][j] = k++;

            }
        }

        for(int i=1; i<=m; i++)
        {
            for(int j=1; j<=n; j++)
                if(i == j) p[i][j] = 0;
                else p[i][j] = oo;
        }

        for(int i=1; i<=m; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(maps[i][j]>='A' && maps[i][j] <='Z')
                    BFS(a[i][j], i, j);
            }
        }

        Prim(k-1);

    }
    return 0;
}
View Code

 

posted on 2016-07-26 16:57  不忧尘世不忧心  阅读(393)  评论(0编辑  收藏  举报