Hrbust 1355 Leyni,罗莉和XianGe (最短路 思维建图,dij优化)


Leyni,罗莉和XianGe
Time Limit: 1000 MSMemory Limit: 65536 K
Total Submit: 128(23 users)Total Accepted: 31(19 users)Rating: Special Judge: No
Description

教授Leyni喜欢跟罗莉一起玩,这次,XianGe也来了,他们处在一个r * c的矩形区域中。Leyni处在矩形区域的入口外(左上角左侧),XianGe处在矩形区域的出口外(右下角右侧),罗莉处在矩形区域内。现在Leyni要喊话给XianGe,可是声音在这个矩形区域内只能横向或者垂直传递,而且,如果某个罗莉听到了声音(听到声音的罗莉不会阻碍声音继续传播),Leyni可以命令她作为传递者向四周传递一次声音,使得与她同一行同一列的罗莉都能听到声音(如下图右侧情况);当然,Leyni也可以让听到声音的罗莉不传递(如下图左侧情况);Leyni处在入口(左上角)的左侧,所以他只能向第一行传递声音;XianGe处在出口(右下角)的右侧,所以他只能接收到最后一行的声音。

如下图所示是一个3 * 3的矩形区域,在矩形区域内有两个罗莉,Leyni命令她们传递声音,并在入口处传递声音给第一行的罗莉,她同时向四周传递声音,第三行的罗莉收到声音后继续传递,使XianGe听到了声音。

现在给出一个矩形区域的大小和各个罗莉的位置情况,Leyni想知道他最少要命令几个罗莉传递声音才能让XianGe听到,请你帮助他!



Input

本题有多组测试数据,输入的第一行是一个整数T代表着测试数据的数量,接下来是T组测试数据。

对于每组测试数据:

1 包含两个以空格分隔的整数rc (2 ≤ r, c ≤ 1000),代表着矩形区域的大小。

2 .. r + 1 r行包含了一个rc列的矩阵,由".""#"组成,其中"#"表示罗莉,"."表示空。

Output

对于每组测试数据:

1 如果Leyni能成功传递声音给XianGe,则输出他最少需要命令多少个罗莉负责传递声音;否则输出-1

Sample Input

1

3 3

.#.

.#.

.#.

Sample Output

2

题解: 看完应该是一个最短路,但是图有点大,正常建图有点虚。根据每个萝莉可以传递它所在行所在列的信息。我们想到,按坐标建图,这样一共只有n+m个点,试着跑了一个没优化的dij,加上优化后,跑出来了,还有注意清空edge 。难点在建图!!!!

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <algorithm>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 3000
using namespace std;
const int N=1005;
int t,n,m;
int vis[maxn];
int dis[maxn];
char mp[3010][3010];
struct rec
{
    int v,w;
};
vector<rec> edge[N*2];
struct cmp
{
    bool operator()(int a,int b)
    {
        return dis[a]>dis[b];
    }
};
void add(int x,int y)
{
    edge[x].push_back((rec){y+n,1});
    edge[y+n].push_back((rec){x,1});

}
void Dijkstra()
{
    priority_queue<int,vector<int>,cmp> Q;
    memset(dis,-1,sizeof(dis));
    memset(vis,0,sizeof(vis));
    int i,u,v;
    Q.push(1);
    dis[1]=0;
    while(!Q.empty())
    {
        u=Q.top();
        Q.pop();
        vis[u]=0;
        if(u==n)
            break;
        for(i=0;i<edge[u].size();i++)
        {
            v=edge[u][i].v;
            if(dis[v]==-1 || dis[v]>dis[u]+edge[u][i].w)
            {
                dis[v]=dis[u]+edge[u][i].w;
                if(!vis[v])
                {
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
    if(dis[n])
    printf("%d\n",dis[n]);
    else
        printf("-1\n");
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n+m;i++)
            edge[i].clear();
        for(int i=1; i<=n; i++)
            scanf("%s",mp[i]+1);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                if(mp[i][j]=='#')
                {
                   add(i,j);
                }
            }
       Dijkstra();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值