题目描述:找一条路径最短条件下的花费最少的路!!!看反了改了一下午!!!
稀疏图,用邻接表,否则超出内存限制
用优先队列储存到达每一个点的时候的状态,重载小于号修改排序规则,这样队首一定是当前条件下最优选择
又有点像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);
}