您的位置:首页 > 其它

zoj 2864 Catch the thief

2011-04-01 16:23 363 查看
WA了五版,贡献了50、60次WA。。。我成功地把这个题的AC率降低了好几个百分点。。。伟大吧。。



纠结两天多了><。



废话不多说了,总之,还是道好题的。



说下题意,给你一个图,无向图,有起点,终点,给出q个询问,询问在时间t的时候,小偷可能在哪几个地点。小偷是沿最短路从起点逃到终点的。



因为最短路可能有多条,所以造成同一时间,小偷所在地点不同。



最短路后,然后找所有的最短路径。以前做过类似的,是从终点往起点找。如果找到点i,dis[i] + edge(i,now) == dis[now],说明这个i点是最短路上的点,然后将它入队,继续找。



关于时间的统计,找到一个点的时候,i 点 到 now点的时间,需要统计下,因为可能一个点会用到多次,所以节点的时间不统计,标记下这个节点是最短路里的,最后再统一加上。只要把 dis[i] + 1 到 dis[now] - 1的时间段都加一即可。但是,WA了一天的我想明白了,这个方法不可取。



我开始的时候没有想清楚,以为q询问的结果再1000以内,所以还挺高兴得开了short型的1000W的数组。然后WA在3秒多,然后一直想特殊情况。。。直到上午,排除所有的特殊情况,想了下,测试了下,发现,确实存在大于1000的结果,事实上,肯定有大于short型的结果的,所以,很悲剧地WA掉了。



网上只有一个程序,是用DFS的,我的想法没有错,所以想办法改进。



把所有询问存一下,把在搜索过程询问时间在 dis[i] + 1 到 dis[now] - 1的时间段内的结果++,最后依次输出这些结果即可。



这个过程完了之后,需要把在最短路径里的点再算上,看看询问的点是否为这些点,如果是的话,这个询问再++,即可。



A掉了,高兴^ ^.



#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <algorithm>
#define MAX 1010
using namespace std;
short map[MAX][MAX];
int dis[MAX];
void SPFA(int from,int to,int n)
{
	queue<int> q;
	bool inq[MAX];
	memset(inq,false,sizeof(inq));
	for(int i=0; i<=n; i++)
		dis[i] = INT_MAX;
	int now = from;
	inq[now] = true;
	dis[now] = 0;
	q.push(now);
	while( !q.empty() )
	{
		int now = q.front();
		q.pop();
		inq[now] = 0;
		for(int k=1; k<=n; k++)
			if( map[now][k] && dis[k] > dis[now] + map[now][k] )
			{
				dis[k] = dis[now] + map[now][k];
				if( !inq[k] )
				{
					q.push(k);
					inq[k] = true;
				}
			}
	}
}
bool b[MAX][MAX];
queue<short> q;	
bool inq[MAX];
int ans[MAX],lala;
int tt[MAX];
int BFS(int from,int to,int n)
{
	bool used[MAX];
	memset(inq,0,sizeof(inq));
	memset(used,false,sizeof(used));
	memset(b,false,sizeof(b));
	memset(ans,0,sizeof(ans));
	q.push(to);
	used[to] = used[from] = inq[to] = true;
	int k;
	while( !q.empty() )
	{
		int now = q.front();
		q.pop(); 
		inq[now] = false;
		for(int i=1; i<=n; i++)
			if( !b[i][now] && map[i][now] && dis[i] != INT_MAX && dis[now] == dis[i] + map[i][now] )
			{			
				used[i] = true;	
				b[i][now] = b[now][i] = true;
				for(k=0; k<lala; k++)
				{
					if( tt[k] >= dis[i]+1 && tt[k] < dis[now] )
						ans[k]++;
				}
				if( !inq[i] )
				{
					inq[i] = true;
					q.push(i);
				}
			}
	}
	for(int i=1; i<=n; i++)  // 如果有在最短路径上的点,就加上去,因为上面没有加这些点 
		for(int k=0; k<lala; k++)
			if( used[i] && dis[i] == tt[k] )
				ans[k]++;
}
int main()
{
	int n,m,s,t,from,to,len;
	int flag = 0;
	while( ~scanf("%d%d%d%d",&n,&m,&s,&t) )
	{
		if( flag )
			printf("/n");
		flag = 1;
		memset(map,0,sizeof(map));
		while( m-- )
		{
			scanf("%d%d%d",&from,&to,&len);
			map[from][to] = map[to][from] = len;
		}
		SPFA(s,t,n);
		scanf("%d",&lala);
		for(int i=0; i<lala; i++)
			scanf("%d",&tt[i]);
		BFS(s,t,n);
		for(int i=0; i<lala; i++)
		{		
			if( tt[i] >= dis[t] || tt[i] == 0 )
				printf("1/n");
			else
				printf("%d/n",ans[i]);
		}
	}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: