【最短路】玛丽卡

 
From SHUXK
玛丽卡
 
   
   
  描述 Description 
 麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
(你可以认为他计算完这个最糟糕的时间后得知了这条堵车的路,他一定可以在这个最糟糕的时间内到达)
编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
   
   
 输入格式 Input Format 
 第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。
接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。
   
   
  输出格式 Output Format 
 输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。
   
   
  样例输入 Sample Input [复制数据] 
 
   
   
  样例输出 Sample Output [复制数据] 
 
   
   
  时间限制 Time Limitation 
 1s



做了这道题,我明白我真的该练一下代码了,这么水的一道题做了我一个半小时。

就是先求一次最短路,然后枚举删除最短路上的每一条边,再求最短路,从答案中找到一个最大值输出。


因为我们的根本目的是求最短路,但是图不是唯一的,因此我们要枚举图的各种情况。但是很明显,如果枚举每一条边,则图的形式太多,太慢。

明显有很大一部分情况求出的最短路是相同的,即如果在原来的最短路上没有修改,则不会影响最短路的长度。


就说我错的地方导致我效率低效的原因吧,以后要引起注意。


1、初值极大和极小不分,混乱。

2、modify模块,把标号修改成了权值。

3、pre数组每次dijkstra都会修改,但是我需要的是原始的最短路上的pre。

4、dijkstra+heap,heap必须首先把所有的元素都放入堆中,而不能只放和起点有边的。

5、无向边只删除了其中一个方向,另一个方向忘记删除。

6、memset在cstring库里,而我只引用了string。


主要就是以上错误,而且除了1,都是静态查错不容易找出来的,所以编程时就需要注意。


#include <cstdio>
#include <string>
#include <cstring>

const long inf = 0x3f3f3f3f;

long dist[1010];
long edge[1010][1010];
bool used[1010];
long pre[1010];
long Prev[1010];

long heap[4010];
long map[1010];
long size = 0;

inline long getint()
{
	long rs=0;bool sgn=1;char tmp;
	do tmp = getchar();
	while (!isdigit(tmp)&&tmp-'-');
	if (tmp == '-'){tmp=getchar();sgn=0;}
	do rs=(rs<<3)+(rs<<1)+tmp-'0';
	while (isdigit(tmp=getchar()));
	return sgn?rs:-rs;	
}
inline void swap(long a,long b)
{
	long tmp = map[heap[a]];
	map[heap[a]] = map[heap[b]];
	map[heap[b]] = tmp;

	tmp = heap[a];
	heap[a] = heap[b];
	heap[b] = tmp;
}

inline void adjust_up(long l)
{
	while (l>1)
	{
		if (dist[heap[l]]<dist[heap[l>>1]]) swap(l,l>>1);
		else break;
		l >>= 1;
	}
}

inline void adjust_down(long l)
{
	while ((l<<=1)<size+1)
	{
		if (l<size&&dist[heap[l+1]]<dist[heap[l]]) l++;
		if (dist[heap[l]]<dist[heap[l>>1]]) swap(l,l>>1);
		else break;
	}
}

inline void insert(long a)
{
	size ++;
	map[a] = size;
	heap[size] = a;
	adjust_up(size);
}

inline void modify(long a)
{
	long l = map[a];
	adjust_up(l);
}

inline long top()
{
	return heap[1];
}

inline void pop()
{
	if (size > 0)
	{
		heap[1] = heap[size--];
		adjust_down(1);
	}
}

long n;

void dijkstra()
{
	size = 0;
	memset(used,0,sizeof used);
	memset(dist,0x3f,sizeof dist);
	memset(pre,0,sizeof pre);

	dist[1] = 0;
	insert(1);
	for (long i=2;i<n+1;i++)
		//if (edge[1][i] < inf)
			insert(i);

	for (long l=1;l<n;l++)
	{
		long u = top();
		long d = dist[u];
		used[u] = true;
		pop();
		for (long v=1;v<n+1;v++)
		{
			if (!used[v] && edge[u][v]<inf && dist[v]>d+edge[u][v])
			{
				dist[v] = d + edge[u][v];
				pre[v] = u;
				modify(v);
			}
		}
	}
}

int main()
{
	freopen("marico.in","r",stdin);
	freopen("marico.out","w",stdout);
	n = getint();
	long m = getint();

	memset(edge,0x3f,sizeof edge);
	for (long i=1;i<m+1;i++)
	{
		long a = getint();
		long b = getint();
		long v = getint();
		edge[a][b] = edge[a][b]<v?edge[a][b]:v;
		edge[b][a] = edge[a][b];
	}
	dijkstra();
	for (long i=1;i<n+1;i++)
		Prev[i] = pre[i];
	long ans = 0;
	long now = n;
	while (Prev[now])
	{
		long tmp = edge[Prev[now]][now];
		edge[Prev[now]][now] = inf;
		edge[now][Prev[now]] = inf;
		dijkstra();
		if (dist[n]<inf&&dist[n]>ans)
			ans = dist[n];
		edge[Prev[now]][now] = tmp;
		edge[now][Prev[now]] = tmp;
		now = Prev[now];
	}
	printf("%ld",ans);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值