Vijos 1082 丛林探险

题目链接:https://vijos.org/p/1082

本题本来是练习SPFA的。我一看DIscuss能用裸搜。果断敲了一个前向星+DFS,居然超时了。后来发现是Next数组开小了,应该开成两倍边数的大小。

后来我又把前向星改成邻接表,也AC了。。最后写一发SPFA。


前向星+DFS+剪枝:(AC):

 

#include <iostream>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

#include <vector>

#include <queue>

#include <algorithm>

using namespace std;



#define INF 0x3f3f3f3f

#define Maxn 5005

#define Maxm 40005<<1



struct Edge

{

    int x;

    int y;

    int c;

    int d;

};



Edge e[Maxm];

int first[Maxn];

int next[Maxm];//注意不要写成next[Maxn],切记

int used[Maxn];

int k;

int s,t;

int n,m;

int mma = INF;



void dfs(int start,int total_len,int total_k)

{

    //加两个剪支,体力值超过范围或者长度必然不是最优两种情况

    if(total_k > k || total_len > mma)

    {

        return;

    }

    if(start == t)

    {

        if(total_k<=k)

        {

            mma = mma>total_len ? total_len : mma;

        }

        return;

    }

    used[start] = 1;

    for(int i=first[start]; i!=-1; i=next[i])

    {

        if(used[e[i].y] == 0)

        {

            dfs(e[i].y,total_len + e[i].d ,total_k + e[i].c);

        }

    }

    used[start] = 0;

}

int main()

{

/*#ifndef ONLINE_JUDGE

    freopen("in.txt","r",stdin);

#endif*/

    scanf(" %d %d",&n,&m);

    memset(first,-1,sizeof(first));

    memset(next,-1,sizeof(next));

    memset(used,0,sizeof(used));



    int temp = m;

    int i = 0;

    while(temp--)

    {

        scanf(" %d %d %d %d",&e[i].x,&e[i].y,&e[i].c,&e[i].d);

        next[i] = first[e[i].x];

        first[e[i].x] = i;

        i++;

        e[i].x = e[i-1].y,e[i].y = e[i-1].x,e[i].c = e[i-1].c,e[i].d = e[i-1].d;

        next[i] = first[e[i].x];

        first[e[i].x] = i;

        i++;

    }

    scanf(" %d %d %d",&s,&t,&k);

    dfs(s,0,0);

    if(mma == INF) printf("-1\n");

    else printf("%d\n",mma);

}

 

邻接表+DFS+剪枝(AC):

 

#include <iostream>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

#include <vector>

#include <queue>

#include <algorithm>

using namespace std;



#define INF 0xffffff

#define Maxn 5005

#define Maxm 40005<<1



struct vertex

{

    int n;

    int length;

    int cost;

};



vector < vertex > graph[Maxn];

int used[Maxn];

int k;

int s,t;

int n,m;

int mma = INF;



void dfs(int start,int total_len,int total_k)

{

    //加两个剪支,体力值超过范围或者长度必然不是最优两种情况

    if(total_k <=k && total_len < mma)

    {

        if(start == t)

        {

            mma = total_len;

        }

        else

        {

            used[start] = 1;

            for(int i=0; i<graph[start].size(); i++)

            {

                if(used[graph[start][i].n] == 0)

                {

                    dfs(graph[start][i].n,total_len + graph[start][i].length,total_k + graph[start][i].cost);

                }

            }

            used[start] = 0;

        }

    }

}

int main()

{

    /*#ifndef ONLINE_JUDGE

        freopen("in.txt","r",stdin);

    #endif*/

    int st,vd,ct,le;

    scanf(" %d %d",&n,&m);

    memset(used,0,sizeof(used));

    int temp = m;

    int i = 0;

    while(temp--)

    {

        scanf(" %d %d %d %d",&st,&vd,&ct,&le);

        vertex one;

        one.n = vd;

        one.length = le;

        one.cost = ct;

        graph[st].push_back(one);



        vertex other;

        other.n = st;

        other.cost = ct;

        other.length = le;

        graph[vd].push_back(other);

    }

    scanf(" %d %d %d",&s,&t,&k);

    dfs(s,0,0);

    if(mma == INF) printf("-1\n");

    else printf("%d\n",mma);

}

 


前向星+SPFA (AC):

声明两个Dist数组,一个代表时间(距离),一个代表体力值,只有两个Dist同时满足条件时,才会更新,也才有机会入队列。

 

#include <iostream>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

#include <vector>

#include <queue>

#include <algorithm>

using namespace std;



#define INF 0x3f3f3f3f

#define Maxn 5005

#define Maxm 40005<<1



struct Edge

{

    int x;

    int y;

    int c;

    int d;

};



Edge e[Maxm];

int first[Maxn];

int next[Maxm];

int used[Maxn];

int distC[Maxn];//体力

int distD[Maxn];//时间



int k;

int s,t;

int n,m;



void spfa(int s)

{

    queue<int> q;

    memset(used,0,sizeof(used));

    used[s] = 1;

    q.push(s);

    while(!q.empty())

    {

        int u = q.front();

        q.pop();

        used[u] = 0;

        for(int i=first[u]; i!=-1; i=next[i])

        {

            int v = e[i].y;

            int c = e[i].c;

            int d = e[i].d;

            if(distD[v] - d > distD[u] && distC[u] + c <=k)

            {

                distD[v] = distD[u] + d;

                distC[v] = distC[u] + c;

                if(used[v] == 0)

                {

                    used[v] = 1;

                    q.push(v);

                }

            }

        }

    }

}

int main()

{

    /*#ifndef ONLINE_JUDGE

        freopen("in.txt","r",stdin);

    #endif*/



    scanf(" %d %d",&n,&m);



    memset(first,-1,sizeof(first));

    memset(next,-1,sizeof(next));

    memset(used,0,sizeof(used));

    memset(distC,0x3f,sizeof(distC));

    memset(distD,0x3f,sizeof(distD));



    int temp = m;

    int i = 0;

    while(temp--)

    {

        scanf(" %d %d %d %d",&e[i].x,&e[i].y,&e[i].c,&e[i].d);

        next[i] = first[e[i].x];

        first[e[i].x] = i;

        i++;

        e[i].x = e[i-1].y,e[i].y = e[i-1].x,e[i].c = e[i-1].c,e[i].d = e[i-1].d;

        next[i] = first[e[i].x];

        first[e[i].x] = i;

        i++;

    }

    scanf(" %d %d %d",&s,&t,&k);

    distD[s] = distC[s] = 0;

    spfa(s);

    if(distD[t] == INF) printf("-1\n");

    else printf("%d\n",distD[t]);

}


 

 

你可能感兴趣的:(OS)