zjut1634——也算是动态规划吧,只是我写的奇怪



Problem C: 单向迷宫

Time Limit: 3 Sec   Memory Limit: 128 MB
Submit: 94   Solved: 2
[ Submit][ Status][ Web Board]

Description

ZJUT有一个单向迷宫,里面所有的道路都是单向的,对于一个固定的节点,能在下一步走到的节点是固定的,Rakkit已经获取了这个迷宫每个节点能直接走到的点是哪个,现在需要你做一些统计。对于每个询问x,y,求出x节点在走y步之后达到的点

Input

对于每组数据
第一行,一个n表示迷宫的节点数
接下来n个数表示每个节点直接可以走到的点
接下来一行一个字母q表示询问的个数
接下来q行每行给出两个字母x,y,表示一个询问

【数据范围】
1<=x<=n<=100000
1<=q<=100000
10<=y<=1000000000

Output

对于每一个询问,给出一个答案,一个答案占一行

Sample Input

3
2 3 1
3
1 1
1 2
2 3

Sample Output

2
3
2





这必须要简化,要省去不必要的向后遍历。然后就写了我2个小时,才终于订正过来
#include<iostream>
#include<algorithm>
#include <stdio.h>
#include<stdlib.h>
#include<string>
using namespace std;
#define M 100010

int head[M],nextt[M],flag[M],dis[M],loop[M],diss[M],front[M],jiechu[M],up[M],flagg[M];
int *circle[M];
int main()
{
	int i,j,n,k,p,num,now_head,q,x,y,jc;
	unsigned int bs;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=1;i<=n;i++)
		{
			head[i]=-1;
			flag[i]=0;
			flagg[i]=0;
			nextt[i]=-1;
			up[i]=-1;
			dis[i]=-1;
			loop[i]=-1;
		}

		for(i=1;i<=n;i++)
		{
			scanf("%d",&p);
			nextt[i]=p;
			up[p]=i;
		}

		k=0;
		for(i=1;i<=n;i++)
		{
			if(flag[i]==0)
			{
				flagg[i]=1;
				p=i;
				while(1)
				{
					flagg[p]=1;
					if(up[p]==-1||flagg[up[p]]==1)
						break;
					p=up[p];
				}
			}
			else continue;
			num=0;
			now_head=k;
			dis[p]=num;
			diss[num]=p;
			flag[p]=1;
			flagg[p]=1;
			head[p]=k;
			p=nextt[p];
			while(1)
			{
				num++;
				if(flag[p]==1)
				{
					if(head[p]==k)
					{
						loop[k]=num-dis[p];
						front[k]=dis[p];
						jiechu[k]=p;
					//	printf("front[%d]=%d,jiechu[%d]=%d\n",k,front[k],k,jiechu[k]);
					}
					else
					{
						jiechu[k]=p;
						front[k]=num;
					//printf("front[%d]=%d,jiechu[%d]=%d\n",k,front[k],k,jiechu[k]);
					}
					break;
				}
				dis[p]=num;
				diss[num]=p;
				head[p]=k;
				flag[p]=1;
				flagg[p]=1;
				p=nextt[p];
			}
			circle[k]=new int[num];
			for(j=0;j<num;j++)
			{
				*(circle[k]+j)=diss[j];
			}
			k++;
		}
		scanf("%d",&q);
		while(q--)
		{
			scanf("%d%d",&x,&y);
		//	cout<<"y="<<y<<endl;
			now_head=head[x];
			bs=y+dis[x];
		//printf("front=%d,jiechu=%d\n",front[now_head],jiechu[now_head]);
			if(bs<front[now_head])
			{
				printf("%d\n",*(circle[now_head]+bs));
			}
			else
			{
				while(1)
				{
				bs-=front[now_head];
				jc=jiechu[now_head];
				now_head=head[jc];
				bs+=dis[jc];
				//printf("new,now_head=%d\n",now_head);
				if(bs<front[now_head])
				{
					printf("%d\n",*(circle[now_head]+bs));
					break;
				}
				else
				{
					if(loop[now_head]==-1)
						continue;
					bs-=front[now_head];
					bs=bs%loop[now_head];
					bs+=front[now_head];
					printf("%d\n",*(circle[now_head]+bs));
					break;
				}
				}
			}
		}
	}
}	





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值