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 }

 

posted @ 2012-04-26 12:45  BeatLJ  阅读(206)  评论(0编辑  收藏  举报