hdu 4297 One and One Story

One and One Story

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 657    Accepted Submission(s): 335


Problem Description
  Have you ever played the romantic Flash game, "One and One Story"? 1 In this story of a boy and a girl and their romance you are to direct them to meet together as they face their euphoria and trials of their relationship.
  You, as a member of the FFF Inquisition,  2 are fed up with such game since you believe that to make things fair, you should not keep providing guidance information while risking remaining forever alone  3 . So you decided to write a program working out guidance for these sweet small lovers on behalf of you. ( Another reason is, you have to help K couples, which would make you somewhat overwhelmed. )
  Fortunately, you are to handle not the Flash game above, but a simplified version: In the game, a maze consists of some rooms connected with one-way hallways. For each room, there is exactly one outgoing hallway here, and it would lead directly to some room (not necessarily a different one). The boy and girl are trapped in (not necessarily different) rooms. In each round of the games, both of them could choose to stay in the current room or walk to the room to which the unique outgoing hallway leads. Note that boy and girl could act independently of each other. Your goal is to come to the reunion between them.
  Your program should determine a pair of numbers (A,B) for each couple of boy and girl, where A represents number of hallway the boy walked through, B the girl, that could lead reunion between them. First, your program should minimize max(A,B). If there are several solutions, you should then guarantee that min(A,B) is minimized subject to above. If, satisfying above conditions, there are still multiple solutions, girl should walk less, that is you should then keep A >= B subject to conditions above. 
  In case they could not reunion, just let A = B = -1.
---------------------------------------------------------------------------------
1It’s available here: http://armorgames.com/play/12409/one-and-one-story
2See http://bakatotest.wikia.com/wiki/FFF_Inquisition
3http://foreveralonecomic.com/
 

Input
  There're several test cases.
  In each test case, in the first line there are two positive integers N and K (1 <= N <= 500000; 1 <= K <= 500000) denoting the number of rooms and number of couples. Rooms a numbered from 1 to N.
  The second line contains n positive integers: the i th integer denotes the number of room to which the hallway going out of room i leads.
The following K lines are queries of several couples. Each query consists of two positive integers in a single line denoting the numbers of rooms where the lovers currently are: first the boy, then the girl.
  Please process until EOF (End Of File).
 

Output
  For each test case you should output exactly K lines, one line per query. Each line consists two integers separated by a space: the integer A and B for this couple.
  See samples for detailed information.
 

Sample Input
  
  
12 5 4 3 5 5 1 1 12 12 9 9 7 1 7 2 8 11 1 2 9 10 10 5 12 5 4 3 5 5 1 1 12 12 9 9 7 1 7 2 8 11 1 2 9 10 10 5
 

Sample Output
  
  
2 3 1 2 2 2 0 1 -1 -1 2 3 1 2 2 2 0 1 -1 -1
 

Source



代码:

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<cstdio>
#include<vector>
using namespace std;
const int N=500010;
struct node
{
	int x,y;
	node(){}
	node(int _x,int _y){x=_x;y=_y;}
};
struct tree
{
	int set[N];
	void init(int n)
	{
		int i;
		for(i=1;i<=n;i++) set[i]=i;
	}
	int find(int x)
	{
		if(set[x]!=x) set[x]=find(set[x]);
		return set[x];
	}
}a,b;
int n,k,pre[N],root[N],dep[N],lca[N],cir[N];
vector<int> edge[N];
vector<node> query[N];
int isroot[N],x[N],y[N];
bool vis[N];
void Input()
{
	int i,p,q;
	a.init(n);
	for(i=1;i<=n;i++)
	{
		edge[i].clear();
		query[i].clear();
	}
	for(i=1;i<=n;i++)
	{
		scanf("%d",&pre[i]);
		edge[pre[i]].push_back(i);
		p=a.find(i);
		q=a.find(pre[i]);
		a.set[p]=q;
	}
	for(i=0;i<k;i++)
	{
		scanf("%d%d",&x[i],&y[i]);
		query[x[i]].push_back(node(y[i],i));
		query[y[i]].push_back(node(x[i],i));
	}
}
void LCA(int u,int depth,int Root)
{
	int i,v,x,y;
	dep[u]=depth;
	root[u]=Root;
	for(i=0;i<edge[u].size();i++)
	{
		v=edge[u][i];
		if(isroot[v]!=-1||u==v) continue;
		LCA(v,depth+1,Root);
		b.set[v]=u;
	}
	vis[u]=true;
	for(i=0;i<query[u].size();i++)
	{
		x=query[u][i].x;
		y=query[u][i].y;
		if(vis[x]&&root[u]==root[x]) lca[y]=b.find(x);
	}
}
void Output()
{
	int i,j,u,v,rootX,rootY,size,X,Y,A,B;
	for(i=0;i<k;i++)
	{
		if(a.find(x[i])!=a.find(y[i])) {puts("-1 -1");continue;}
		if(root[x[i]]==root[y[i]])
		{
			j=lca[i];
			printf("%d %d\n",dep[x[i]]-dep[j],dep[y[i]]-dep[j]);
			continue;
		}
		u=dep[x[i]];
		v=dep[y[i]];
		rootX=root[x[i]];
		rootY=root[y[i]];
		size=cir[a.find(rootX)];
		X=(isroot[rootY]-isroot[rootX]+size)%size;
		Y=(isroot[rootX]-isroot[rootY]+size)%size;
		if(max(u+X,v)<max(u,v+Y)) A=u+X,B=v;
		else if(max(u+X,v)>max(u,v+Y)) A=u,B=v+Y;
		else if(min(u+X,v)<min(u,v+Y)) A=u+X,B=v;
		else if(min(u+X,v)>min(u,v+Y)) A=u,B=v+Y;
		else A=u+X,B=v;
		printf("%d %d\n",A,B);
	}
}
int main()
{
	while(~scanf("%d%d",&n,&k))
	{
		Input();
		int i,j,t,c;
		memset(isroot,-1,sizeof(isroot));
		memset(vis,false,sizeof(vis));
		for(i=1;i<=n;i++) if(a.set[i]==i)
		{
			t=i;
			while(1)
			{
				if(vis[t]) break;
				vis[t]=true;
				t=pre[t];
			}
			c=0;
			isroot[t]=c++;
			for(j=pre[t];j!=t;j=pre[j]) isroot[j]=c++;
			cir[i]=c;
		}
		memset(lca,-1,sizeof(lca));
		memset(vis,false,sizeof(vis));
		b.init(n);
		for(i=1;i<=n;i++) if(isroot[i]!=-1) LCA(i,0,i);
		Output();
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值