UVA10537

此题就是反向求最短路然后注意一个公式20
假设从a->b在a 时的距离值是q 则b是不阔能小于 x的其中x-(x/20)=q;注意(x/20)代表的是向上取整现在这就是x>=(20/19*q) 我们阔以认为x是(20/19*q)(然后(x/20)就是花费
这样的话会节省不少讨论呢。。。。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
struct diann
{
	int value;
	int num;
	diann()
	{
	}
};
ll dist[5000], pre[5000];
int hashh[5000];
int m;
diann dian[5000];
int diantot;
typedef pair < int, diann >p;
struct edgee
{
	int to;
};
edgee edge[8000];
int first[5000], nextt[8000];
int edgetot = 0;
void addedge(int a, int b)
{
	edge[edgetot].to = b;
	nextt[edgetot] = first[a];
	first[a] = edgetot;
	edgetot++;
	edge[edgetot].to = a;
	nextt[edgetot] = first[b];
	first[b] = edgetot;
	edgetot++;
}
struct com
{
	bool operator()(p a, p b)
	{
		return a.first>b.first;
	}
};
void distra(diann num,int tot,int begin,int end,int times)
{
	for (int i = 0; i < tot; i++)dist[i] = 4611686018427387904, pre[i] = -1;
	dist[num.num] = begin;
	priority_queue<p, vector<p>, com>que;
	que.push(p(begin, num));
	while (!que.empty())
	{
		int num = que.top().second.num; int costkind = que.top().second.value<='Z'?1:0;
		ll value = costkind ? ceil(ceil(dist[num] *1.0*20/19.0)*1.0/20) :1;
		p temp = que.top();
		que.pop();
		if (dist[num] < temp.first)continue;
		for (int i = first[num]; i != -1; i = nextt[i])
		{
				int now = edge[i].to;
				if (dist[now] > dist[num] + value)
				{
					dist[now] = dist[num] + value;
					pre[now] = num;
					que.push(p(dist[now], dian[now]));
				}
				if (dist[now] == dist[num] + value&&dian[pre[now]].value > dian[num].value)
					pre[now] = num;
		}
	}
	printf("Case %d:\n", times);
	printf("%lld\n", dist[hashh[end]]);
	for (int i = hashh[end];i!=-1; i = pre[i])
	{
		if (pre[i] != -1)
			printf("%c-", dian[i].value);
		else
			printf("%c", dian[i].value);
	}
	printf("\n");
}
int main()
{
	//for (ll i = 1, kk = 0; kk <= 62; i = i * 2, kk++)
		//cout << i << endl;
	int k = 1;
	while (scanf("%d", &m) && m != -1)
	{
	
		diantot = 0;
		edgetot = 0;
		for (int i = 0; i < 5000; i++)first[i] = -1,hashh[i]=-1;
		getchar();
		for (int i = 0; i < m; i++)
		{
			char a, b;
			scanf("%c", &a);
			getchar();
			scanf("%c", &b);
			getchar();
			if(hashh[a]==-1)hashh[a] = diantot++,dian[hashh[a]].num = hashh[a], dian[hashh[a]].value = a;
			if(hashh[b]==-1)hashh[b] = diantot++, dian[hashh[b]].num = hashh[b], dian[hashh[b]].value = b;
			addedge(hashh[a], hashh[b]);
		}

		int d;
		scanf("%d", &d);
		getchar();
		char a, b;
		scanf("%c", &a);
		getchar();
		scanf("%c", &b);
		if (m == 0)
		{
			printf("Case %d:\n", k);
			printf("%d\n", d);
			printf("%c\n", a);
			k++;
			continue;
		}
		distra(dian[hashh[b]], diantot, d, a, k);
		k++;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值