SCU-4527 NightMare2(最短路+二分)

 

思路就是二分枚举起点到达终点能携带的最多财宝数量,原本的spfa是在dis[v]>dis[u]+w时就松弛起点到v点距离,但是这里加了一个条件要携带值为mid的财宝,所以还要判断一下这条边是否可以携带mid财宝。还要注意题目没有说输入的u和v哪个是起点哪个是终点

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
const ll inf =3e9;
struct edge
{
    int v,nxt;
    ll cap,w;

}e[50000+10];
int head[10000+10],vis[10000+10];
ll dis[10000+10];
int n,m;
ll k;
int tot;
bool spfa(ll mid)
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=inf;
        vis[i]=0;
    }
    queue<int>q;
    while(!q.empty()) q.pop();
    dis[1]=0;
    vis[1]=1;
    q.push(1);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].nxt)
        {
            int v=e[i].v;
            ll cap=e[i].cap;
            ll w=e[i].w;
            if((dis[v]>dis[u]+w)&&(cap>=mid)&&(dis[u]+w)<=k)
            {
                dis[v]=dis[u]+w;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return (dis[n]<=k);

}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        tot=0;
        ll low=0,up=-1,mid,ans=-1;
        scanf("%d%d%lld",&n,&m,&k);
        for(int i=1;i<=n;i++) head[i]=-1;
        for(int i=0;i<m;i++)
        {
            int u,v;
            ll c,w;
            scanf("%d%d%lld%lld",&u,&v,&c,&w);
            e[tot].v=v;
            e[tot].cap=c;
            e[tot].w=w;
            e[tot].nxt=head[u];
            head[u]=tot++;
            e[tot].v=u;
            e[tot].cap=c;
            e[tot].w=w;
            e[tot].nxt=head[v];
            head[v]=tot++;
            up=max(up,c);

        }
        while(low<=up)
        {
            //cout<<mid<<endl;

            mid=(low+up)/2;
            if(spfa(mid))
            {
                low=mid+1;
                ans=mid;

            }
            else
                up=mid-1;
        }
        //cout<<"low:"<<low<<"   up:"<<up<<endl;
        if(ans==-1)
            printf("Poor RunningPhoton!\n");
        else
            printf("%lld\n",ans);



    }
    return 0;
}

 

posted @ 2018-08-06 18:51  eason99  阅读(72)  评论(0编辑  收藏  举报