Vijos 1082 丛林探险

来源:互联网 发布:三星打印机m2070端口 编辑:程序博客网 时间:2024/06/26 02:23

题目链接: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<<1struct 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<<1struct 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<<1struct 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]);}


原创粉丝点击