ZOJ Monthly, July 2011 - B Cake Robbery

http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=4366

(题意大概就是给出一些在凸多边形内部不相交的切割,求出边数最大的多边形的边数)

比赛的后半段时间差不多是我在搞这道题,搞了个错误的算法,一直WA到最后。

由于watashi神没有给出月赛的报告! scorpio牛说出一个很飘逸的叫“括号序列”

的算法。

大概步骤:

(1)对一个切割 i,j (i<j) ,i的出度加1,j的入度加1

(2)从小到大,找第一个出度不为0的开始点st。

(3)从st开始顺时针扫描。

       顺时针压每条原始边。(这里的压边用压0表示)

       遇到出度不为0的,压左括号和边。(说明这个点可能是多边形的一个顶点)

       遇到入度不为0的,压右括号和边。(说明这个点可能是多边形的一个顶点)

(4)再次扫描到st点,结束。

#include <iostream>

#include <cstdio>

#include <algorithm>

#include <string.h>

#include <stack>

#include <cmath>

#include <vector>

using namespace std;



struct node

{

	int r; 

	int c; 

}a[10005];



int main()

{

	int N,M,l,r;

	while(scanf("%d %d",&N,&M)!=EOF)

	{

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

			  a[i].r=0,a[i].c=0;

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

		  {

			  scanf("%d %d",&l,&r);

			  if(l>r)

				  swap(l,r);

              a[l].c+=1;

			  a[r].r+=1;

		  }

		  if(M==0)

		  {

			  printf("%d\n",N);

			  continue;

		  }



		  int st=0;

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

		  {

			  if(a[i].c==0)

				  continue;

			  st = i;

			  break;

		  }

          stack<int>s;

		  while(s.size()>0)

			  s.pop();

		  while(a[st].c>0)

		  { 

			  s.push(st);

		      s.push(0);

              a[st].c-=1;

		  }

		  int pur = st;

		  int ans = 0;

		  int cnt = 0;



		  while(1)

		  {

              pur = pur%N+1;

			  s.push(0);       //压原始边(边缘)

			  if(pur == st)

				  break;

			  while(a[pur].r>0)

			  {

				  a[pur].r-=1;

				  cnt=0;

				  while(s.size()>0 && s.top()==0)

				  {

					cnt+=1;

					s.pop();

				  }

				  ans = max(cnt,ans);

				  s.pop();

				  if(s.size()==0)

				  {

					s.push(st);    //栈空,还没结束,继续压左括号和边

					s.push(0);

				  }

				  else

				    s.push(0);            //压边(替换消掉的多边形)

			   }

              

			   while(a[pur].c>0)

			   {

				 a[pur].c-=1;

				 s.push(pur);

				 s.push(0);    

			   }

		  }



		  cnt = 0;

          while(s.size()>0 && s.top()==0)

		  {

			  cnt+=1;

			  s.pop();

		  }

		  ans = max(ans,cnt);

		  printf("%d\n",ans);

	}

	return 0;

}



你可能感兴趣的:(ZOJ)