USACO 2011 March Silver Meeting Place

题目描述

Bessie and Jonell are great friends. Since Farmer John scrambleswhere the cows graze every day, they are sometimes quite far from each otherand can't talk. The pastures and paths on FJ's farm form a 'tree' structure.Each pasture has exactly one distinct path to any other pasture, and eachpasture (except pasture #1, the 'root') also has a single parent node. Bessieand Jonell have decided that they will always meet at the closest pasture thatthat is both an ancestor of Jonell's pasture and of Bessie's pasture. FJcreated a map of his N (1 <= N <= 1,000) pastures (conveniently numbered1..N) that tells the parent P_i (1 <= P_i <= N) of each pasture exceptpasture 1, which has no parent. FJ has released his daily grazing schedule forthe next M (1 <= M <= 1,000) days, so Bessie and Jonell are decidingwhere they should meet each day for gossip. On day k, Bessie is in pasture B_k(1 <= B_k <= N) and Jonell is in pasture J_k (1 <= J_k <= N). Givena map and schedule, help Bessie and Jonell find their meeting places. Consider,for example, the following farm layout:

                            Pasture      Parent Pasture
             [1]           ---------    ----------------
            / | \              1              ---
           /  |  \             2               1 
         [2] [3] [6]           3               1
         /        | \          4               2
        /         |  \         5               8
      [4]        [8]  [9]      6               1
                /   \          7               8
               /     \         8               6
             [5]     [7]       9               6
Here are the meeting places that Bessie and Jonell would choose given a six day schedule of their initial grazing locations:
              Bessie      Jonell       Meeting Place
             --------    --------     ---------------
                 2           7               1
                 4           2               2
                 1           1               1
                 4           1               1
                 7           5               8
                 9           5               6

 输入

* Line 1: Two space-separated integers: N and M * Lines 2..N: Linei contains a single integer that describes the parent of pasture i: P_i * LinesN+1..N+M: Line k+N describes Bessie and Jonell's respective pastures with twospace-separated integers: B_k and J_k

 输出

* Lines 1..M: Line j contains the meeting place Bessie and Jonellwould use for line j+N of the input

 样例输入

96

1

1

2

8

1

8

6

6

2 7

4 2

3 3

4 1

7 5

9 5

样例输出

1

2

3

1

8

6

题解:tarjan算法和RMQ倍增算法两种做法。

#include <cstdio>
#include <cmath>
#define N 1005
int n,m,k,first[N*2],next[N*2],v[N*2],s;
int first1[N*2],next1[N*2],v1[N*2],ans[N];
int x,y,z,cnt,f[N],id[N*2];
bool vis[N];
using namespace std;
inline int find(int x)
{
	if (f[x]==x) return x;
	int t=find(f[x]);
	f[x]=t;
	return t;
}
inline void hb(int x,int y)
{
	int xx=find(x),yy=find(y);
	if (xx!=yy) f[xx]=yy;
}
inline void tarjan(int root)
{
	vis[root]=1;
	for (int i=first1[root];i;i=next1[i]) 
	  if (vis[v1[i]]) ans[id[i]]=find(v1[i]);
	for (int i=first[root];i;i=next[i])
	  if (!vis[v[i]])
	  {
	  	tarjan(v[i]);
	  	hb(v[i],root);
	  }
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=2;i<=n;i++)
	{
		scanf("%d",&x);
		next[++cnt]=first[i];
		first[i]=cnt;
		v[cnt]=x;
		next[++cnt]=first[x];
		first[x]=cnt;
		v[cnt]=i;
	}
	cnt=0;
	for (int i=1;i<=m;i++) 
	{
		scanf("%d%d",&x,&y);
		next1[++cnt]=first1[x];
		first1[x]=cnt;
		v1[cnt]=y;
		id[cnt]=i;
		next1[++cnt]=first1[y];
		first1[y]=cnt;
		v1[cnt]=x;
		id[cnt]=i;
	}
	for (int i=1;i<=n;i++) f[i]=i;
	tarjan(1);
	for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}
//RMQ倍增算法
#include <cstdio>
#include <cmath>
#define N 1005
int n,m,k,first[N*2],next[N*2],v[N*2],s;
int x,y,z,cnt,dep[N],f[N][20];
bool vis[N];
using namespace std;
inline void dfs(int x,int k)
{
    dep[x]=k;
    vis[x]=1;
    for (int i=first[x];i;i=next[i])
    if (!vis[v[i]])
    {
    	f[v[i]][0]=x;
    	dfs(v[i],k+1);
    }		
}
inline int find(int x,int y)
{
	if (dep[x]<dep[y])
	{
		int t=x;x=y;y=t;
	}
	for (int i=log2(n);i>=0;i--)
	  if (dep[f[x][i]]>=dep[y]) x=f[x][i];
	if (x==y) return x;
	for (int i=log2(n);i>=0;i--)
	  if (f[x][i]!=f[y][i])
	  {
	  	x=f[x][i];
	  	y=f[y][i];
	  } 
	return f[x][0];
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=2;i<=n;i++)
	{
		scanf("%d",&x);
		next[++cnt]=first[i];
		first[i]=cnt;
		v[cnt]=x;
		next[++cnt]=first[x];
		first[x]=cnt;
		v[cnt]=i;
	}
	dfs(1,1);
	for (int j=1;j<=log2(n);j++)
	   for (int i=1;i<=n;i++)
	     f[i][j]=f[f[i][j-1]][j-1];
	for (int i=1;i<=m;i++) 
	{
		scanf("%d%d",&x,&y);
		printf("%d\n",find(x,y));
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/zhouhongkai06/article/details/80472374
今日推荐