您的位置:首页 > 其它

hihoCoder 第38周 二分答案+BFS

2015-03-22 21:48 113 查看
题意 在这个游戏里面,海域是N个战略点(编号1..N)组成,其中红色的点表示有敌人驻扎,猫头像的的点表示该地图敌军主力舰队(boss)的驻扎点,虚线表示各个战略点之间的航线(无向边)。

在游戏中要从一个战略点到相邻战略点需要满足一定的条件,即需要舰队的索敌值大于等于这两点之间航线的索敌值需求。

由于提高索敌值需要将攻击机、轰炸机换成侦察机,舰队索敌值越高,也就意味着舰队的战力越低。

另外在每一个战略点会发生一次战斗,需要消耗1/K的燃料和子弹。必须在燃料和子弹未用完的情况下进入boss点才能与boss进行战斗,所以舰队最多只能走过K条航路。

现在Nettle想要以最高的战力来进攻boss点,所以他希望能够找出一条从起始点(编号为1的点)到boss点的航路,使得舰队需要达到的索敌值最低,并且有剩余的燃料和子弹。

特别说明:两个战略点之间可能不止一条航线,两个相邻战略点之间可能不止一条航线。保证至少存在一条路径能在燃料子弹用完前到达boss点。

思路
考虑到直接做FS,有这个索敌值限制确实不好做。但是,一旦确定了索敌值,那么超过这个值得边可以认为没有,那么这个题就是非常基础的BFS。因此我们想到可以枚举索敌值~然后,枚举的话,自然希望二分答案(当然这个专题就是二分嘛~)。把能否到达T作为因变量,索敌值作为自变量,很显然,这是非递减函数,可以二分~复杂度可以接受~

#include <stdio.h>
#include <cstring>
#include <queue>
#include <map>
#include <iostream>
using namespace std;
const int maxn = 10005;
const int maxm = 100005;
const int maxw = 1000000;
typedef pair<int,int> PII;
#define fi first
#define se second
#define MP make_pair

int n,m,k,t;
struct Edge{
int u,v,c,next;
Edge(int u=0,int v=0,int c=0,int next = -1):u(u),v(v),c(c),next(next){

}
void set(int u=0,int v=0,int c=0,int next = -1){
this->u = u;
this->v = v;
this->c = c;
this->next = next;
}
}edge[maxm<<1];
int g[maxn];

int addEdge()
{
for(int i=0;i<m;i++)
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
//cout<<g[u]<<endl<<g[v]<<endl<<endl;
edge[i<<1].set(u,v,c,g[u]);
edge[(i<<1)|1].set(v,u,c,g[v]);
g[u] = i<<1;
g[v] = (i<<1)|1;
//cout<<g[u]<<endl<<g[v]<<endl<<endl;
}
}

int init()
{
memset(g,-1,sizeof(g));
}

queue<PII> q;
int mark[maxn];
bool bfs(int limit)
{
while(q.size()!=0)
q.pop();
memset(mark,0,sizeof(mark));
q.push(MP(1,0));
while(q.size()!=0)
{
PII tmp = q.front();
q.pop();
//		cout<<tmp.fi<<endl;
if(tmp.se >= k)
return 0;
for(int e=g[tmp.fi];e!=-1;e=edge[e].next)
{
if(edge[e].c > limit)
continue;
if(edge[e].v == t)
{
return 1;
}
if(mark[edge[e].v] == 1)
continue;
mark[edge[e].v] = 1;
q.push(MP(edge[e].v,tmp.se+1));
}
}
return 0;
}

int main()
{
scanf("%d%d%d%d",&n,&m,&k,&t);
int i,j;
init();
addEdge();
int l,r,mid;
int ans = 0;
l = 1;
r = maxw+1;
while(l < r)
{
mid = (l+r)/2;
//	cout<<l<<endl<<r<<endl<<mid<<endl<<endl;
if(bfs(mid))
{
r = mid;
ans = mid;
}
else
{
l = mid + 1;
}
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: