CCF201403-4 无线网络(最短路)

传送门:CCF201403-4 无线网络

若把距离小于等于r的两路由器视为存在一条边,则题目可以归为求无权无向图的最短路径,就变得十分简单了。

直接跑一遍spfa,求得点1到其他点的最短路。因为题目要求的是最少经过的中转路由器的数量,而我们用spfa求得的最短路是包含了终点的,故要输出点1到点2的最短路的值-1 (s)。

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 256;
struct point
{
    ll x, y;
}p[maxn];

struct node //后面的spfa需要用到的结构
{
    int x, k; //x为路由器的编号,k为选取x后已增设的路由器数量
    node() {}
    node(int X, int K): x(X), k(K) {}
};

int n, m, k, dis[maxn], vis[maxn];
ll r, d[maxn][maxn];

void read()
{
    cin >> n >> m >> k >> r;
    for(int i = 1; i <= n+m; ++i)
        cin >> p[i].x >> p[i].y;

    r *= r; 
    //r的最大值为1e8,r^2为1e16,不会爆long long,直接用r^2,省去麻烦的开方操作
    for(int i = 1; i < n+m; ++i)
        for(int j = i+1; j <= n+m; ++j)
        {
            ll x1 = p[i].x, x2 = p[j].x;
            ll y1 = p[i].y, y2 = p[j].y;
            d[i][j] = d[j][i] = (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);
            //其实可以开一个vector<int>数组,存相连的点
            //在这里判断d[i][j]是否小于等于r,存进vector数组中
            //后面spfa的for循环的范围就会小一些
            //但由于m+n的数量级非常小,且博主很懒QAQ,就没有写了
        }
    }

void spfa()
{
    for(int i = 2; i <= n+m; ++i)
        dis[i] = INF;
    dis[1] = 0;

    queue <node> q;
    q.push(node(1, 0));
    while(!q.empty())
    {
        node cur = q.front();
        q.pop();
        vis[cur.x] = 0;
        for(int i = 2; i <= n+m; ++i)
        {
            if(cur.k >= k && i > n) //当已增设的路由器数量等于k,就不能再增设了
                break;
            if(d[cur.x][i] <= r && dis[i] > dis[cur.x]+1) //每条边权值相当于1
            {
                dis[i] = dis[cur.x]+1;
                if(!vis[i])
                {
                    if(i > n)
                        q.push(node(i, cur.k+1)); //增设路由器
                    else
                        q.push(node(i, cur.k));
                    vis[i] = 1;
                }
            }
        }
    }
}

void solve()
{
    spfa();
    cout << dis[2]-1; 
}

int main()
{
    read();
    solve();
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值