hdu 2377 zoj 2913

点击打开题目

本题就是求中心区域

设置一个数组res[i]用来存放每一个区域i到达公交路线上所有区域的最大值,最后再求res[i]的最小值,则i即是求得的中心区域;

利用BFS搜索以及滚动数组的特性即可以求出。

 

 

参见代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

using namespace std;
#define MAX(a, b) (a > b ? a : b)

const int MAXN = 10000;
const int INF = 1000000;

int Graph[MAXN][10];//"邻接矩阵",Graph[i][j]表示编号为i的地区第j个相邻地区的编号;
int mz[MAXN];//mz[id]表示与第id的地区相邻的数目;
int nz, nr;
int cur;//记录当前公交站点次序,cur = 0表示当前为第一站
int reach[MAXN];//reach[i] == cur 表示地区i已经在第cur+1站访问过了
int res[MAXN];//res[i]中存放的是,每个地区i到达公交路线上所有区域的最大值;而最后所求的中心区域即是res的最小值

void BFS( int s )
{
     int a, b, i;
     int val, now;//val表示搜寻层数,也是距离,now表示BFS搜寻过程中当前结点;
     queue <int> q[2];//利用滚动数组,由于是一层一层的访问,所以可以利用滚动数组的特性
     a = 0, b = 1, val = 0;
     if(reach[s] < cur)//表明区域s还未被访问
     {
          q[b].push(s);
          reach[s] = cur;
          res[s] = MAX(res[s], val+1);
     }
     while( !q[b].empty())
     {
          swap(a, b);
          val++;
          while(!q[a].empty())
          {
               now = q[a].front();
               q[a].pop();
               for(i = 0; i < mz[now]; ++i)
               {
                    if(reach[ Graph[now][i] ] < cur)
                    {
                         q[b].push(Graph[now][i]);
                         reach[ Graph[now][i] ] = cur;
                         res[ Graph[now][i] ] = MAX(res[Graph[now][i] ], val+1);
                    }
               }
          }
     }
}

int main()
{
     int T;
     int i, j;
     int id;//地区编号
     int mr;//每条公交路线所经过的区域
     int ret, center;
     cin>>T;
     while(T--)
     {
          memset(reach, -1, sizeof(reach));
          memset(res, 0, sizeof(res));
          cur = 0;
          cin>>nz>>nr;
          for(i = 0; i < nz; ++i)
          {
               cin>>id;
               cin>>mz[id];
               for(j = 0; j < mz[id]; ++j)
                    cin>>Graph[id][j];
          }
          
          for(i = 0; i < nr; ++i)
          {
               cin>>mr;
               for(j = 0; j < mr; ++j)
               {
                    cin>>id;
                    BFS(id);
                    cur++;
               }
          }
          center = -1, ret = INF;
          for(i = 0; i < 10000; ++i)
          {
               if(reach[i] == cur-1 && res[i] < ret)//表明公交路线上所有区域已经访问完了,而reach[i] == cur-1就是判断是否访问完的标志
               {
                    ret = res[i];
                    center = i;
               }
          }
          cout<<ret<<" "<<center<<endl;
     }
    return 0;
}


/**


1
17 2
7400 6 7401 7402 7403 7404 7405 7406
7401 6 7412 7402 7400 7406 7410 7411
7402 5 7412 7403 7400 7401 7411
7403 6 7413 7414 7404 7400 7402 7412
7404 5 7403 7414 7415 7405 7400
7405 6 7404 7415 7407 7408 7406 7400
7406 7 7400 7405 7407 7408 7409 7410 7401
7407 4 7408 7406 7405 7415
7408 4 7409 7406 7405 7407
7409 3 7410 7406 7408
7410 4 7411 7401 7406 7409
7411 5 7416 7412 7402 7401 7410
7412 6 7416 7411 7401 7402 7403 7413
7413 3 7412 7403 7414
7414 3 7413 7403 7404
7415 3 7404 7405 7407
7416 2 7411 7412
5 7409 7408 7407 7405 7415
6 7415 7404 7414 7413 7412 7416
*/


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值