USACO[Holiday 2010 Bonus Competition/gold]cowpol

显然,对于一个党派,相距最远的两头牛中至少有一头是这个党派中深度最大的牛之一(这一点联系求树的直径,先随便从一点找最远,再从那儿找最远)。

所以每个党派的范围=max{最深的牛的深度+某头牛的深度-它们的最近公共祖先的深度*2,某头牛属于这个党派}。

问题的主要矛盾是LCA,然后,写了第一个Tarjan的LCA,由于数据太BT,要非递归,并且,即使这样下面的代码在Windows下无法编译(好像是因为开的内存太大了),但可以在USACO的测评系统下通过,所以在Linux下可以用的。

然后,LCA还有其它的算法可以做,有空再弄其它的,LCA这还是第一次写。

CODE:

/*

PROG: cowpol

LANG: C++

ID: boleyn.2

*/

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-6-4

DESCRIPTION:

TITLE: Cow Politics [Andre Kessler, 2009]

CONTENT:

Farmer John’s cows are living on N (2 <= N <= 200,000) different

pastures conveniently numbered 1..N. Exactly N-1 bidirectional cow

paths (of unit length) connect these pastures in various ways, and

each pasture is reachable from any other cow pasture by traversing

one or more of these paths (thus, the pastures and paths form a

graph called a tree).

The input for a particular set of pastures will specify the parent

node P_i (0 <= P_i <= N) for each pasture. The root node will specify

parent P_i == 0, which means it has no parent.

The cows have organized K (1 <= K <= N/2) different political parties

conveniently numbered 1..K. Each cow identifies with a single

political party; cow i identifies with political party A_i (1 <=

A_i <= K). Each political party includes at least two cows.

The political parties are feuding and would like to know how much

‘range’ each party covers. The range of a party is the largest

distance between any two cows within that party (over cow paths).

For example, suppose political party 1 consists of cows 1, 3, and

6, political party 2 consists of cows 2, 4, and 5, and the pastures

are connected as follows (party 1 members are marked as -n-):

  -3-

   |

  -1-

 / | \

2  4  5

      |

     -6-

The greatest distance between any two pastures of political party

1 is 3 (between cows 3 and 6), and the greatest distance for political

party 2 is 2 (between cows 2 and 4, between cows 4 and 5, and between

cows 5 and 2).

Help the cows determine party ranges.

TIME LIMIT: 2 seconds

MEMORY LIMIT: 64MB

PROBLEM NAME: cowpol

INPUT FORMAT:

* Line 1: Two space-separated integers: N and K

* Lines 2..N+1: Line i+1 contains two space-separated integers: A_i

        and P_i

SAMPLE INPUT (file cowpol.in):

6 2

1 3

2 1

1 0

2 1

2 1

1 5

OUTPUT FORMAT:

* Lines 1..K: Line i contains a single integer that is the range of

        party i.

SAMPLE OUTPUT (file cowpol.out):

3

2

*/

#include <fstream>

using std::ifstream;

using std::ofstream;

using std::endl;

#include <list>

using std::list;

namespace sj

{

          template<unsigned int size>

          class UFSET

          {

                int p[size];

                int rank[size];

                public:

                void MAKE_SET()

                {

                     for (int i=0;i<size;rank[i++]=0) p[i]=i;

                }

                int FIND_SET(int x)

                {

                    if (p[x]==x) return x;

                    else return p[x]=FIND_SET(p[x]);

                }

                void UNION(int x,int y)

                {

                     x=FIND_SET(x);

                     y=FIND_SET(y);

                     if (x==y) return;

                     if (rank[x]<rank[y]) p[x]=y;

                     else

                     {

                        p[y]=x;

                        if (rank[x]==rank[y]) rank[x]++;

                     }

                }

          };

}

using namespace sj;

 

class Application

{

      ifstream cin;

      ofstream cout;

      static const int MAXN=200000;

      int N,K;

      int A[MAXN+1],P[MAXN+1];

      int size[MAXN+1];

      int root;

      list<int> child[MAXN+1];

      int deep[MAXN+1];

      int deepest[MAXN+1];

      list<int> question[MAXN+1];

      UFSET<MAXN+1> set;

      bool visited[MAXN+1];

      int ancestor[MAXN+1];

      int dfs(int node,int depth=1,int father=0)

      {

          deep[node]=depth;

          if (deep[deepest[A[node]]]<depth) deepest[A[node]]=node;

          question[A[node]].push_back(node);

          for (list<int>::iterator i=child[node].begin();

                                   i!=child[node].end();i++)

              if (*i!=father) dfs(*i,depth+1,node);

      }

      int LCA(int root)

      {

          static int depth;

          static int _node[MAXN+1];

          static int _father[MAXN+1];

          static list<int>::iterator _i[MAXN+1];

         

          _node[depth]=root;

          _father[depth]=0;

          _i[depth]=child[_node[depth]].begin();

          ancestor[_node[depth]]=_node[depth];

         

          for (;;)

          {

              int& node=_node[depth];

              int& father=_father[depth];

              list<int>::iterator& i=_i[depth];

             

              if (*i==father) i++;             

              if (i!=child[node].end())

              {

                 depth++;

                 _node[depth]=*i;

                 _father[depth]=node;

                 _i[depth]=child[_node[depth]].begin();

                 ancestor[_node[depth]]=_node[depth];

              }

              else

              {

                  visited[node]=true;

                  if (node==deepest[A[node]])

                  {

                     for (list<int>::iterator i=question[A[node]].begin();

                                              i!=question[A[node]].end();i++)

                         if (visited[*i])

                     {

                         int get=deep[node]+deep[*i]

                                 -deep[ancestor[set.FIND_SET(*i)]]*2;

                         if (size[A[node]]<get) size[A[node]]=get;

                     }

                  }

                  else if (visited[deepest[A[node]]])

                  {

                       int get=deep[node]+deep[deepest[A[node]]]

                               -deep[ancestor[set.FIND_SET(deepest[A[node]])]]*2;

                       if (size[A[node]]<get) size[A[node]]=get;

                  }

                  depth–;

                  if (depth<0) break;

                  set.UNION(_node[depth],*_i[depth]);

                  ancestor[set.FIND_SET(*_i[depth])]=_node[depth];

                  _i[depth]++;

              }

          }

      }

      /*

      int LCA(int node,int father=0)

      {

          ancestor[node]=node;

          for (list<int>::iterator i=child[node].begin();

                                   i!=child[node].end();i++)

              if (*i!=father)

              {

                 LCA(*i,node);

                 set.UNION(node,*i);

                 ancestor[set.FIND_SET(*i)]=node;

              }

          visited[node]=true;

         

          if (node==deepest[A[node]])

          {

             for (list<int>::iterator i=question[A[node]].begin();

                                      i!=question[A[node]].end();i++)

                 if (visited[*i])

                 {

                    int get=deep[node]+deep[*i]

                            -deep[ancestor[set.FIND_SET(*i)]]*2;

                    if (size[A[node]]<get) size[A[node]]=get;

                    //cout<<“LCA”<<node<<” “<<*i

                    //    <<“=”<<ancestor[set.FIND_SET(*i)]<<endl;

                 }

          }

          else if (visited[deepest[A[node]]])

          {

               int get=deep[node]+deep[deepest[A[node]]]

                       -deep[ancestor[set.FIND_SET(deepest[A[node]])]]*2;

               if (size[A[node]]<get) size[A[node]]=get;

               //cout<<“LCA”<<node<<” “<<deepest[A[node]]

               //    <<“=”<<ancestor[set.FIND_SET(deepest[A[node]])]<<endl;

          }

      }

      */

      public:

      Application(const char* input,const char* output)

                        :cin(input),cout(output)

      {

                        cin>>N>>K;

                        for (int i=1;i<=N;i++)

                            cin>>A[i]>>P[i];

      }

      ~Application()

      {

                    cin.close();

                    cout.close();

      }

      int run()

      {

          for (int i=1;i<=N;i++)

          {

              if (P[i]) child[P[i]].push_back(i);

              else root=i;

              child[i].push_back(P[i]);

          }

          dfs(root);

          set.MAKE_SET();

          LCA(root);

          for (int i=1;i<=K;i++)

              cout<<size[i]<<endl;

          return 0;

      }

};

 

int main()

{

    static

    Application app(“cowpol.in”,“cowpol.out”);

    return app.run();

}

 

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注