赚钱啦
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
5
-
描述
-
某国家里有N个城市,分别编号为0~N-1,一个精明的商人准备从0号城市旅行到N-1号城市,在旅行的过程中,从一个城市移动到另外一个城市需要有一定的花费,并且从A城市移动到B城市的花费和B城市移动到A城市的花费相同,但是,从A城市移动到B城市能赚取的钱和从B城市移动到A城市赚的钱不一定相同。
现在,已知各个城市之间移动的花费和城市之间交易可赚取的金钱,求该商人在从0号城市移动到N-1号城市的过程中最多能赚取多少钱?
-
输入
-
第一行是一个整数T(T<=10)表示测试数据的组数
每组测试数据的第一行是两个整数N,M表示,共有N个城市(1<N<=1000),M条路(1<=M<=1000)
随后的M行,每行有5个正整数,前两个数a,b(0<=a,b<N)表示两个城市的编号。后面的三个数c,u,v分别表示在a,b城市之间移动的花费,a城市移动到b城市可赚取的资金,b城市移动到a城市可赚取的资金。
(0<=c,u,v<=1000)
输出
-
如果商人能够在旅行过程中赚取无限多的资金,则输出$$$
否则输出他在移动过程中最多能赚取的资金数量
如果只会赔钱的话就输出一个负数,表示最少赔的钱数。
样例输入
-
2 2 1 0 1 10 11 11 3 3 0 1 10 16 0 1 2 10 15 5 0 2 20 32 0
样例输出
-
$$$ 12
来源
- 2011年ACM队队长选拨赛
-
第一行是一个整数T(T<=10)表示测试数据的组数
与最短路不同的是这道题在题意上有很大的变更,求的是能获取最大资金,但方法可以用Spfa,或者bellman算法,只不过在存双向图的时候要特别注意,这里介绍一下bellman算法,代码还是挺简洁的;可以用邻接矩阵储存权值,就是在利用bellman算法的时候再反向判断一下另一个顶点就可以了,具体看代码:有不足之处望多多指教,谢谢:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=-0x3f3f3f3f;//注意;
const int N=1000+10;
struct node
{
int u,v,c,a,b;
} a[N];
int d[N];
int spfa(int n,int m)
{
for(int i=0; i<n; i++)
d[i]=i==0?0:INF;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
if(d[a[j].v]<d[a[j].u]+a[j].a)//判断终点(两点中被指向的那个)
{
d[a[j].v]=d[a[j].u]+a[j].a;
if(i>=n-1)//存在正环图;
return 1;
}
if(d[a[j].u]<d[a[j].v]+a[j].b)//判断起点;
{
d[a[j].u]=d[a[j].v]+a[j].b;
if(i>=n-1)
return 1;
}
}
return 0;
}
int main()
{
int t,n,m,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
int f=0;
for(i=0; i<m; i++)
{
scanf("%d%d%d%d%d",&a[i].u,&a[i].v,&a[i].c,&a[i].a,&a[i].b);
a[i].a-=a[i].c,a[i].b-=a[i].c;
if(a[i].a+a[i].b>0)
f=1;
}
if(f)
printf("$$$\n");
else
{
int k=spfa(n,m);
if(k)
printf("$$$\n");
else
printf("%d\n",d[n-1]);
}
}
return 0;
}
自我感觉代码比较简短,易懂,有的地方还可以改进优化;