Luogu P1462 通往奥格瑞玛的道路

搜索

提供一种不一样的做法。

我在写这个题的时候刚刚学了二分和搜索 还不会最短路,就把这个题当做二分题写了。可能是数据比较水吧。首先看到最小值最大或者最大值最小,我们的第一直觉就是二分答案。

我们二分最大值,我们只走那些小于等于二分的答案的路,如果我们能够走到终点,就说明我们设置的条件比较弱,我们就可以减小二分的答案,当我们走不到终点的时候,就说明我们二分的条件比较严,我们就应该调大我们二分的答案,一直这样下去我们就能找到一个比较精确的值,当这个条件精确到唯一的一个值的时候,我们就二分到了我们要的答案。

二分答案很重要的就是check()函数了,很多大佬都是写的最短路(dijkstral/spfa),将掉血量看成路的长度,看看符合条件的掉血量是否符合条件,然后再调整mid值,继续二分。二分的复杂度为\(O(log(n))\),然后再乘上最短路的时间复杂度,就是整体的时间复杂度。但是我写这个题的时候还不会写最短路,之好写了搜索,但可能是数据比较水,被我水过了,当然,我后续会补上关于最短路的题解。

以下就是我的早期代码,可能存在的问题比较多,倘若有什么问题,还望大家不吝赐教,指出我的错误。

最后献上我丑陋的代码

#include<iostream>
#include<cstdio>
using namespace std;
struct bian
{
    int to,nt,dis;
}e[100001];
int f[10001],head[10001],tot,ans;
bool flag=0;
int n,m,b,x,y,z;
void add(int from,int to,int dis)
{
    e[++tot].to=to;
    e[tot].dis=dis;
    e[tot].nt=head[from];
    head[from]=tot;
}
void check(int fr,int l,int x,int q)
{   
    if(f[1]>q||f[n]>q) {flag=0;return;}
    if(fr==n)          {flag=1;return;}
    for(int i=head[fr];i;i=e[i].nt)
    {
        if(f[e[i].to]<=q&&x-e[i].dis>0&&e[i].to!=l)
        {
            check(e[i].to,fr,x-e[i].dis,q); 
        }
        if(flag==1)return;
    }
}
int main()
{
    cin>>n>>m>>b;
    for(int i=1;i<=n;++i)scanf("%d",&f[i]);
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);add(y,x,z);
    }
    int l=0,r=2147483646;
    check(1,0,b,2147483646);
    if(flag==0)
    {
        cout<<"AFK";
        return 0;
    }
    while(l<=r)
    {
        flag=0;
        int mid=(l+r)>>1;
        check(1,0,b,mid);
        if(flag==1)
        {
            r=mid-1;
            ans=mid;
        }
        else l=mid+1;
    }
    cout<<ans;
    return 0;
}

update

已经补上关于最短路的题解(SPFA)

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
const int N=10010;
struct bian
{
    int to,nt,dis;
}e[100001];
int n,m,b,x,y,z,tot,ans;
int f[N],head[N];
long long dis[N];
bool vis[N];
void add(int from,int to,int dis)
{
    e[++tot].to=to;
    e[tot].dis=dis;
    e[tot].nt=head[from];
    head[from]=tot;
}
bool check(int mid)
{   
    if(f[1]>mid||f[n]>mid)return 0;
    memset(dis,0x3f,sizeof(dis));
    queue<int>q;
    q.push(1);
    vis[1]=1;dis[1]=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();vis[x]=0;
        for(int i=head[x];i;i=e[i].nt)
        {
            if(f[e[i].to]>mid)continue;
            if(dis[e[i].to]>dis[x]+e[i].dis)
            {
                dis[e[i].to]=dis[x]+e[i].dis;
                if(!vis[e[i].to])
                {
                    q.push(e[i].to);
                    vis[e[i].to]=1;
                }
            }
        }
    }
    return dis[n]<b;
}
int main()
{
    cin>>n>>m>>b;
    for(int i=1;i<=n;++i)scanf("%d",&f[i]);
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);add(y,x,z);
    }
    int l=0,r=2147483646;
    if(!check(2147483646))
    {
        cout<<"AFK";
        return 0;
    }
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))
        {
            r=mid-1;
            ans=mid;
        }
        else l=mid+1;
    }
    cout<<ans;
    return 0;
}

效率高了一倍,珍爱生命,远离 乱搞

全部评论

相关推荐

hso_:哈哈哈哈哈哈我没offer一样在同一道题开喷了
投递深圳同为数码等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务