nyoj_183_赚钱啦

/*赚钱啦
时间限制: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)
输出
    如果商人能够在旅行过程中赚取无限多的资金,则输出$$$
    否则输出他在移动过程中最多能赚取的资金数量
    如果只会赔钱的话就输出一个负数,表示最少赔的钱数。
样例输入



3
2 1
0 1 10 11 11
3 3
0 1 10 16 0
1 2 10 15 5
0 2 20 32 0
2 1
0 1 10 111 4



样例输出



$$$
12

$$$



最短路径的演化题。


#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define inf 0x3f3f3f3f
struct Node
{
	int v;
	int w;
	int next;
}edge[2010];
int count[1010];
int dist[1010];
bool used[1010];
int head[1010];
int num,f;
int n,m;
void add_edge(int a,int b,int c,int d)
{
	edge[num].v = b;
	edge[num].w = d - c;        //权值存为该净赚的钱 
	edge[num].next = head[a];
	head[a] = num++;	
}
void init()
{
	memset(used,false,sizeof(used));
	memset(count,0,sizeof(count));
}
int spfa()
{
	init();
	int i;
	queue<int>Q;
	for(i=1;i<=n;i++)
	{
		dist[i] = - inf;    //初始为负无穷 
	} 
	dist[1] = 0;
	used[1] = true;
	Q.push(1);
	while(!Q.empty())
	{
		int u = Q.front();
		Q.pop();
		used[u] = false;
		count[u]++;
		if(count[u]>n)      //该点进队次数大于n次,表示负圈存在 
		{
			return 1;
		}
		for(i=head[u];i!=-1;i=edge[i].next)
		{
			int v = edge[i].v;
			int w = edge[i].w; 
			if(dist[v] < dist[u] + w)
			{
				dist[v] = dist[u] + w;
				if(used[v]==false)
				{
					used[v] = true;
					Q.push(v);
				}
			}
		}
	}
	return 0;
}
int main()
{
	int T,t;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		int i,j;
		int a,b,c,d,e;
		num = 1;f = 0;
		memset(head,-1,sizeof(head));
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
			if(d+e>2*c)      //这条道路来回都是能净赚钱 
            {  
                f = 1;  
            }
            add_edge(a+1,b+1,c,d);    //个人爱好,从一号点开始存 
			add_edge(b+1,a+1,c,e);
		}
		
		if(f || spfa())
		{
			printf("$$$\n");		
		}
		else
		{
			printf("%d\n",dist[n]);
		}
	}
	return 0;
} 


你可能感兴趣的:(nyoj_183_赚钱啦)