前言
这道题感谢朋友的帮助,这里是他的博客地址:
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
#include
#include
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].wif (!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[n]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[n]);
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);//输出
}