您的位置:首页 > 其它

洛谷P1462-通往奥格玛瑞的路【日常图论,二分查找,最短路,SPAF】

2018-01-13 16:24 281 查看

前言

这道题感谢朋友的帮助,这里是他的博客地址:

http://blog.csdn.net/sugar_free_mint

题目

一个无向图,每个点和边都有一定的权值,要求从点1到点2在经过边的权值小于b的情况下经过点的最大权值尽量小

输入

4 4 8(4个点,4条边,要求边的权值小于8)

8(第一个点的权值)

5

6

10

2 1 2(2到1有条边权值为2)

2 4 1

1 3 4

3 4 3

输出

10

解题思路

先看看能否到达,不然输出AFK。然后如果可以,用二分法找最优答案

代码

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct woc{
int w,x,y,next;
};//邻接表
woc a[100001];
int n,m,b,xx,yy,ww,ls[10001],head,tail,cost[10001],t,state[10001];
bool v[10001];
long long f[10001];
bool spfa(int money)//如果经过点权值小于money,是否可以到达
{
memset(f,127/3,sizeof(f));//初始化
if (cost[1]>money) return false;//没用
head=0;
tail=1;
v[1]=true;
state[1]=1;
f[1]=0;//初始化
while (head!=tail)
{
head++;//入队
head=(head-1)%n+1;//循环队列
t=ls[state[head]];//联通该点的一条边
while (t!=0)
{
if (f[a[t].x]+a[t].w<f[a[t].y])
b915

{
f[a[t].y]=f[a[t].x]+a[t].w;
if (!v[a[t].y] && cost[a[t].y]<=money)//看看点是否满足要求
{
tail++;//入队
tail=(tail-1)%n+1;//循环队列
state[tail]=a[t].y;
v[a[t].y]=true;//标记
}
}
t=a[t].next;//下一条边
}
v[state[head]]=false;//解封
}
if (f
<b) return true;
return false;//返回结果
}
int main()
{
int u=0,mid,l,r;
scanf("%d%d%d",&n,&m,&b);
for (int i=1;i<=n;i++)
{
scanf("%d",&cost[i]);
r=max(r,cost[i]);
}
l=max(cost[1],cost
);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&xx,&yy,&ww);
a[++u].x=xx;
a[u].y=yy;
a[u].w=ww;
a[u].next=ls[xx];
ls[xx]=u;
a[++u].y=xx;
a[u].x=yy;
a[u].w=ww;
a[u].next=ls[yy];
ls[yy]=u;//无向图
}
if (!spfa(1000000001)) {printf("AFK");return 0;}
//是否可以到达
while (l<=r)
{
mid=(l+r)/2;//二分
if (spfa(mid)) r=mid-1;
else l=mid+1;
}
printf("%d",l);//输出
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: