POJ 1724 ROADS

 题目描述:找一条路径最短条件下的花费最少的路!!!看反了改了一下午!!!

稀疏图,用邻接表,否则超出内存限制

 

用优先队列储存到达每一个点的时候的状态,重载小于号修改排序规则,这样队首一定是当前条件下最优选择

又有点像bfs

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <queue>
#include <stack>
#include <algorithm>
#include <string.h>
#include <math.h>

#define INF 0x3f3f3f3f
#define NUM 10010
using namespace std;

int k,n,r;
int s[NUM],d[NUM];
int first[NUM],nextn[NUM],len[NUM],coin[NUM];

struct node{
    int i,cost,dis;

    bool operator < (const node &b)const{
        return dis>b.dis;
    }
};

priority_queue<node>que;

int main(){
    int ans=INF;
    memset(first,-1,sizeof(first));
    memset(nextn,-1,sizeof(nextn));

    while(!que.empty()){
        que.pop();
    }

    scanf("%d%d%d",&k,&n,&r);
    for(int i=1;i<=r;i++){
        scanf("%d%d%d%d",&s[i],&d[i],&len[i],&coin[i]);
        nextn[i]=first[s[i]];
        first[s[i]]=i;
    }

//    for(int i=1;i<=r;i++){
//        printf("%d\t%d*\n",first[i],nextn[i]);
//    }

    node a;
    a.i=1;
    a.cost=0;
    a.dis=0;
    que.push(a);
    while(!que.empty()){
        node b=que.top();
        que.pop();

        if(b.i==n){
            ans=b.dis;
            break;
        }

        for(int i=first[b.i];i!=-1;i=nextn[i]){
            if(b.cost+coin[i]<=k){   //减枝
                node c;
                c.i=d[i];
                c.cost=b.cost+coin[i];
                c.dis=b.dis+len[i];
                que.push(c);
            }
        }
    }
    printf("%d\n",ans==INF?-1:ans);
}

 

错误代码:按照spfa修改的

在读入的时候如果有重复的路,只读最优路。但是每次松弛不能保证一定是最优解,样例输入就是一个例子

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <queue>
#include <stack>
#include <algorithm>
#include <string.h>
#include <math.h>

#define INF 0x3f3f3f3f
#define NUM 10010
using namespace std;

int k,n,r;
int s[NUM],d[NUM];
int first[NUM],nextn[NUM],len[NUM],coin[NUM];
int mark[NUM];
int dis[NUM],cost[NUM];

queue<int >que;

int main(){
    memset(nextn,-1,sizeof(nextn));
    memset(first,-1,sizeof(first));   //如果不为-1,最后next都会等于0,多出第零条边
    memset(mark,0,sizeof(mark));
    memset(dis,0,sizeof(dis));
    memset(cost,0x3f,sizeof(cost));
    while(!que.empty())
        que.pop();
    scanf("%d%d%d",&k,&n,&r);
    for(int i=1;i<=r;i++){
        scanf("%d%d%d%d",&s[i],&d[i],&len[i],&coin[i]);
        int flag=0;
        for(int j=first[s[i]];j!=-1;j=nextn[j]){
            if(s[j]==s[i]&&d[j]==d[i]){
                flag=1;
                if(coin[i]<coin[j]){
                    coin[j]=coin[i];
                    len[j]=len[i];
                    break;
                }
                else if(coin[i]==coin[j]&&len[i]<len[j]){
                    len[j]=len[i];
                    break;
                }
            }
        }
        if(flag)continue;
        nextn[i]=first[s[i]];
        first[s[i]]=i;
//        for(int i=1;i<=r;i++){
//            printf("%d %d %d*\n",i,first[i],nextn[i]);
//        }
//        printf("\n\n");
    }



    que.push(1);
    cost[1]=0;
    while(!que.empty()){
        int x=que.front();
        que.pop();
        mark[x]=0;

        for(int i=first[x];i!=-1;i=nextn[i]){
            //printf("%d %d %d %d %d %d**\n",i,x,s[i],d[i],cost[d[i]],cost[x]+coin[i]);
            if(cost[d[i]]>cost[x]+coin[i]){
                cost[d[i]]=cost[x]+coin[i];
                dis[d[i]]=dis[x]+len[i];
                if(!mark[d[i]]){
                    que.push(d[i]);
                    mark[d[i]]=1;
                }
                //printf("%d %d %d\n",d[i]);
            }
        }
    }
    //printf("%d\n",cost[n]);
    printf("%d\n",cost[n]>k?-1:dis[n]);
}

 

MLE。。。 

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <queue>
#include <stack>
#include <algorithm>
#include <string.h>
#include <math.h>

#define INF 0x3f3f3f3f

using namespace std;

int n,k,r;
int mark[10010];
int g[10010][10010];
int len[10010][10010];
int dis[10010];
int w[10010];

int main(){
    int s,d,l,t,ans=0;
    memset(mark,0,sizeof(mark));
    memset(g,0x3f,sizeof(g));
    memset(len,0x3f,sizeof(len));
    memset(dis,0x3f,sizeof(dis));
    memset(w,0x3f,sizeof(w));
    scanf("%d%d%d",&k,&n,&r);
    while(r--){
        scanf("%d%d%d%d",&s,&d,&l,&t);
        if(t<g[s][d]){
            g[s][d]=g[d][s]=t;
            len[s][d]=len[d][s]=l;
        }
        else if(t==g[s][d]&&len[s][d]>l)
            len[s][d]=len[d][s]=l;
    }

    dis[1]=0;
    w[1]=0;
    for(int i=0;i<n;i++){
        int index,p=INF;
        for(int j=1;j<=n;j++)
            if(!mark[j]&&dis[j]<p)
                p=dis[index=j];

        mark[index]=1;
        for(int j=1;j<=n;j++)
            if(!mark[j]&&dis[j]>dis[index]+g[index][j]){
                dis[j]=dis[index]+g[index][j];
                w[j]=w[index]+len[index][j];
            }
    }
    printf("%d\n",dis[n]<=k?w[n]:-1);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值