题目链接:http://poj.org/problem?id=1724
题目大意:给定最大费用K(走这些路所能用的最大钱数),点的个数N,边的条数R; 接着R行表示S,D,L,T表示从S到D的路的长度为L,花费为T; 求从1~N的最短路的长度。
分析:类似于最短路,多了一个限制条件,这时我们可以用优先队列来存,用spfa求最短路。让距离小的优先,距离相同的 时候让花费小的优先,判断当前点是否能到达下一点,如果能到,放入队列,直到找到目的地时跳出。如果不能到达,返回-1。
感想:其实思想还是差不多,在最短路的基础上加了一个限制条件做了一个变形,还是要深入理解最短路,用的还挺多的,记得比赛的时候我们刚开始想的也是最短路,不知道怎么去加那个限制条件,想想又觉得是网络流,网络流学的也不好,敲完模板不知道怎么去改,还是自己学的东西太少,要好好下功夫了。
比赛链接:https://cn.vjudge.net/contest/158506#overview
Code:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;
const int maxn=105;
int tot,n,maxx;
struct node
{
int y,di,fee;
node(int yy=0,int dii=0,int fe=0)
{
y=yy,di=dii,fee=fe;
}
friend bool operator < (node a,node b)
{
if(a.di==b.di)
return a.fee>b.fee;//花费
else
return a.di>b.di;//距离
}
} eg[maxn];
vector<node>G[maxn];
priority_queue<node>q;
int spfa()
{
while(!q.empty())
q.pop();
q.push(node(1,0,0));
while(!q.empty())
{
node xx=q.top();
q.pop();
if(xx.y==n)//到达目的地直接跳出,返回最小花费
return xx.di;
for(int i=0; i<G[xx.y].size(); i++)
{
if(xx.fee+G[xx.y][i].fee<=maxx)//如果剩下的钱还够走到下一条路,继续走,直到到达目的地
{
q.push(node(G[xx.y][i].y,xx.di+G[xx.y][i].di,xx.fee+G[xx.y][i].fee));
}
}
}
return -1;
}
int main()
{
int k,r;
while(~scanf("%d%d%d",&maxx,&n,&r))
{
for(int i=0;i<=n;i++)
G[i].clear();
int a,b,c,d;
for(int i=0; i<r; i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
G[a].push_back(node(b,c,d));
}
printf("%d\n",spfa());
}
return 0;
}
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790
题目大意:给你n个点,m条无向边,每条边都有长度d和花费p,给定起点s和终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
分析:本题是双重权值的最短路径问题,做法跟一般的最短路差不多。
要注意最短路长度相同的情况下最小花费的更新。
Code:
#define INF 0x3f3f3f3f
const int maxn=1005;
int vis[maxn],dis[maxn],cost[maxn];
int mp1[maxn][maxn],mp2[maxn][maxn];
int n,m;
void dij(int s,int t)
{
for(int i=1; i<=n; i++)
{
dis[i]=mp1[s][i];
cost[i]=mp2[s][i];
}
dis[s]=0,cost[s]=0;
vis[s]=1;
for(int i=2; i<=n; i++)
{
int minn=INF,pos=0;
for(int j=1; j<=n; j++)
{
if(!vis[j]&&minn>dis[j])
{
minn=dis[j];
pos=j;
}
}
// cout<<minn<<"* ";
vis[pos]=1;
for(int j=1; j<=n; j++)
{
if(!vis[j])
{
if(dis[j]>dis[pos]+mp1[pos][j])
{
dis[j]=dis[pos]+mp1[pos][j];
cost[j]=cost[pos]+mp2[pos][j];
}
else if(dis[j]==dis[pos]+mp1[pos][j]&&cost[j]>cost[pos]+mp2[pos][j])//注意
{
cost[j]=cost[pos]+mp2[pos][j];
}
}
}
}
if(dis[t]==INF)
printf("0 0\n");
else
printf("%d %d\n",dis[t],cost[t]);
}
void init()//初始化
{
memset(vis,0,sizeof(vis));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(i==j)
{
mp1[i][j]=0;
mp2[i][j]=0;
}
else
{
mp1[i][j]=INF;
mp2[i][j]=INF;
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
int a,b,d,p,x,y;
init();
for(int i=0; i<m; i++)
{
scanf("%d%d%d%d",&a,&b,&d,&p);
if(mp1[a][b]>d||(mp1[a][b]==d&&mp2[a][b]>p))
{
mp1[a][b]=mp1[b][a]=d;//长度
mp2[a][b]=mp2[b][a]=p;//花费
}
}
scanf("%d%d",&x,&y);
dij(x,y);
}
return 0;
}
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 15143 | Accepted: 5470 |
Description
Bob and Alice used to live in the city 1. After noticing that Alice was cheating in the card game they liked to play, Bob broke up with her and decided to move away - to the city N. He wants to get there as quickly as possible, but he is short on cash.
We want to help Bob to find the shortest path from the city 1 to the city N that he can afford with the amount of money he has.
Input
The second line contains the integer N, 2 <= N <= 100, the total number of cities.
The third line contains the integer R, 1 <= R <= 10000, the total number of roads.
Each of the following R lines describes one road by specifying integers S, D, L and T separated by single blank characters :
- S is the source city, 1 <= S <= N
- D is the destination city, 1 <= D <= N
- L is the road length, 1 <= L <= 100
- T is the toll (expressed in the number of coins), 0 <= T <=100
Notice that different roads may have the same source and destination cities.
Output
If such path does not exist, only number -1 should be written to the output.
Sample Input
5 6 7 1 2 2 3 2 4 3 3 3 4 2 4 1 3 4 1 4 6 2 1 3 5 2 0 5 4 3 2
Sample Output
11
Source
HDU 3790 最短路径问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 26110 Accepted Submission(s): 7781
(1<n<=1000, 0<m<100000, s != t)
3 2 1 2 5 6 2 3 4 5 1 3 0 0
9 11