COJ1115(Special Operation)

题目链接

题目大意:给定一棵树,求最大点独立集中点的数目。

这题昨晚一开始想到可以转化为求二部图的最大匹配来做,没估计复杂度,最后超时了。

后来就考虑把树分成两部分,取结点较多的那部分作为结果,提交后WA。

再后来,我考虑给树定一个根结点,然后分层,统计每层的结点数目,然后再转化为DP问题去做,相当于是分层DP,结果还是WA。

昨天晚上躺在床上时,突然想到曾经听说过树形DP,难道这题正是?今天翻了下刘汝佳的白书,学习了下树形DP,然后果断AC。

AC的代码
 1 #include <stdio.h>

 2 #include <vector> 

 3 #define MAX(a,b) ((a)>(b)?(a):(b))

 4 #define N 50000

 5 

 6 using namespace std;

 7 

 8 vector<int> g[N];

 9 

10 int p[N],d[N],c[N],sums[N],sumgs[N],dmax,n;

11 

12 void read_tree()

13 {

14   int i,u,v;

15   for(i=1;i<n;i++)

16   {

17     scanf("%d%d",&u,&v),u--,v--;

18     g[u].push_back(v);

19     g[v].push_back(u);

20   }

21 }

22 void dfs(int u,int fa)

23 {

24   int i,v;

25   d[u]=(fa==-1?0:d[fa]+1);

26   dmax=MAX(dmax,d[u]);

27   for(i=0;i<g[u].size();i++)

28   {

29     v=g[u][i];

30     if(v!=fa) dfs(v,p[v]=u);

31   }

32 }

33 void dp()

34 {

35   int i,j;

36   for(i=dmax;i>=0;i--)

37   {

38     for(j=0;j<n;j++)

39     {

40       if(d[j]!=i) continue;

41       c[j]=MAX(sums[j],sumgs[j]+1);

42       if(i>0) sums[p[j]]+=c[j];

43       if(i>1) sumgs[p[p[j]]]+=c[j];

44     }

45   }

46 }

47 int main()

48 {

49   int i;

50   while(~scanf("%d",&n))

51   {

52     for(i=0;i<n;i++)  g[i].clear();

53     memset(sums,0,sizeof(sums));

54     memset(sumgs,0,sizeof(sumgs));

55     dmax=0;

56     read_tree();

57     dfs(0,-1);

58     dp();

59     printf("%d\n",c[0]);

60   }

61   return 0;

62 }

 

超时的代码
 1 #include <stdio.h>

 2 #include <memory.h>

 3 #define N 50001

 4 int x[N],y[N],u[N],v[N],next[N],first[N],n;

 5 char vis[N];

 6 int con(int i,int j)

 7 {

 8   int e;

 9   for(e=first[i];e;e=next[e]) if(v[e]==j) return 1;

10   return 0;

11 }

12 int path(int i)

13 {

14   int j;

15   for(j=1;j<=n;j++)if((con(i,j)||con(j,i))&&!vis[j])

16   {

17     vis[j]=1;

18     if(y[j]==-1 || path(y[j]))

19     {

20       x[i]=j;

21       y[j]=i;

22       return 1;

23     }

24   }

25   return 0;

26 }

27 int maxmatch()

28 {

29   int i,cnt=0;

30   for(i=1;i<=n;i++)if(x[i]==-1)

31   {

32     memset(vis,0,sizeof(vis));

33     cnt+=path(i);

34   }

35   return cnt;

36 }

37 int main()

38 {

39   int i,j,e;

40   freopen("in.txt","r",stdin);

41   freopen("out.txt","w",stdout);

42   while(~scanf("%d",&n))

43   {

44     memset(first,0,sizeof(first));

45     for(e=1;e<n;e++)

46     {

47       scanf("%d%d",&u[e],&v[e]);

48       next[e]=first[u[e]];

49       first[u[e]]=e;

50     }

51     printf("%d\n",n-maxmatch()/2);

52   }

53   return 0;

54 }

 

你可能感兴趣的:(Opera)