Strategic game POJ

//题意:就是你需要派最少的士兵来巡查每一条边。相当于求最少点覆盖,用最少的点将所有边都覆盖掉
//题解:
//因为这是一棵树,所以对于每一条边的两个端点,肯定要至少有一个点需要放入士兵,那么对于x->y这一条边
//dp[x][0]=0 表示在x这一点上不放人士兵
//dp[x][1]=1 表示在x这一个点上放入士兵
//那么就有
//dp[x][0]+=dp[y][1];
//dp[x][1]+=min(dp[y][0],dp[y][1]);

//注意这一道题不需要建立一个图,然后再去dfs,因为题目上就是按树从根到叶逐渐给出的。所以可以直接存
//belong用来表示每一个点的层数,pre表示它的父亲节点

第一次我是建了一个图去找dp,然后就MLE了

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1500;
 7 struct edge
 8 {
 9     int v,next;
10 }e[maxn];
11 int cnt,head[maxn],dp[maxn][5];
12 void add_edge(int x,int y)
13 {
14     e[cnt].v=y;
15     e[cnt].next=head[x];
16     head[x]=cnt++;
17 }
18 int n;
19 void dfs(int x,int pre)
20 {
21     dp[x][0]=0;
22     dp[x][1]=1;
23     for(int i=head[x];i!=-1;i=e[i].next)
24     {
25         int to=e[i].v;
26         //printf("%d %d
",x,to);
27         if(to==pre)
28         {
29             //printf("**%d**%d
",x,to);
30             continue;
31         }
32         dfs(to,x);
33         dp[x][0]+=dp[to][1];
34         dp[x][1]+=min(dp[to][1],dp[to][0]);
35     }
36 }
37 int main()
38 {
39     while(~scanf("%d",&n))
40     {
41         memset(head,-1,sizeof(head));
42         cnt=0;
43         memset(dp,0,sizeof(dp));
44         int x,y,sum,u,flag=0;
45         for(int i=1;i<=n;++i)
46         {
47             scanf("%d:(%d)",&x,&sum);
48 
49             x++;
50             if(flag==0)
51             {
52                 flag=1;
53                 u=x;
54             }
55             while(sum--)
56             {
57                 scanf("%d",&y);
58                 y++;
59                 add_edge(x,y);
60                 add_edge(y,x);
61             }
62         }
63         //printf("%d**
",u);
64         dfs(u,u);
65         printf("%d
",min(dp[u][0],dp[u][1]));
66     }
67     return 0;
68 }
View Code

正解:

 1 //题意:就是你需要派最少的士兵来巡查每一条边。相当于求最少点覆盖,用最少的点将所有边都覆盖掉
 2 //题解:
 3 //因为这是一棵树,所以对于每一条边的两个端点,肯定要至少有一个点需要放入士兵,那么对于x->y这一条边
 4 //dp[x][0]=0 表示在x这一点上不放人士兵
 5 //dp[x][1]=1 表示在x这一个点上放入士兵
 6 //那么就有
 7 //dp[x][0]+=dp[y][1];
 8 //dp[x][1]+=min(dp[y][0],dp[y][1]);
 9 
10 //注意这一道题不需要建立一个图,然后再去dfs,因为题目上就是按树从根到叶逐渐给出的。所以可以直接存
11 //belong用来表示每一个点的层数,pre表示它的父亲节点
12 #include<stdio.h>
13 #include<string.h>
14 #include<iostream>
15 #include<algorithm>
16 using namespace std;
17 const int maxn=1505;
18 int belong[maxn],pre[maxn],dp[maxn][5],cnt;
19 int n;
20 void DP(int x,int index)
21 {
22     dp[x][0]=0;
23     dp[x][1]=1;
24     for(int i=1;i<=n;++i)
25     {
26         if(pre[i]==x)
27         {
28             DP(i,index+1);
29             dp[x][0]+=dp[i][1];
30             dp[x][1]+=min(dp[i][0],dp[i][1]);
31         }
32     }
33 }
34 int main()
35 {
36     while(~scanf("%d",&n))
37     {
38         memset(pre,0,sizeof(pre));
39         memset(dp,0,sizeof(dp));
40         memset(belong,0,sizeof(belong));
41         cnt=0;
42         int x,y,sum,u,flag=0;
43         for(int i=1;i<=n;++i)
44         {
45             scanf("%d:(%d)",&x,&sum);
46             x++;
47             belong[x]=++cnt;
48             if(flag==0)
49             {
50                 flag=1;
51                 u=x;
52             }
53             cnt++;
54             while(sum--)
55             {
56                 scanf("%d",&y);
57                 y++;
58                 pre[y]=x;
59 //                add_edge(x,y);
60 //                add_edge(y,x);
61                 belong[y]=cnt;
62             }
63         }
64         pre[u]=-1;
65         DP(u,1);
66         printf("%d
",min(dp[u][0],dp[u][1]));
67     }
68     return 0;
69 }
View Code
原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11663803.html