uva 10859 - Placing Lampposts dp

题意:

  有n个节点,m条边,无向无环图,求最少点覆盖,并且在同样点数下保证被覆盖两次的变最多

分析:

1.统一化目标,本题需要优化目标有两个,一个最小灯数a,一个最大双覆盖边数b,一大一小,应该归一成,a及单覆盖边数c,\( x=Ma+c \) 为最小化目标,\( M>\Delta c \)

2.决策分析,只有两种放灯与不放,如不放灯则需要父节点必须放灯,故需要父节点状态,设\( f(i,j) \)为节点i在父节点状态为j时的最小x值,j为0代表不放灯,j为1代表放

  \begin{cases}
    sum\{d(k,0)|k为i所有子节点\}+(i为根节点?0:1)&,i不放灯\\
    sum\{d(k,1)|k为i所有子节点\}+M+(i不为根节点且j==0?1:0)&,i\ 放灯
    \end{cases}

 

 

代码如下

 1 /*
 2 author:jxy
 3 lang:C/C++
 4 university:China,Xidian University
 5 **If you need to reprint,please indicate the source**
 6 */
 7 #include <iostream>
 8 #include <cstdio>
 9 #include <cstdlib>
10 #include <cstring>
11 #include <algorithm>
12 using namespace std;
13 int n,m;
14 int first[1005];
15 int Next[2005],U[2005];
16 bool vis[1005][2];
17 int ans[1005][2];
18 int cnt;
19 int M=1<<11;
20 void add(int u,int v) //双向边
21 {
22     Next[cnt]=first[u]; first[u]=cnt; U[cnt++]=v;
23     Next[cnt]=first[v]; first[v]=cnt; U[cnt++]=u;
24 }
25 int dfs(int i,int j,int f)//i为当前节点,j为0代表父节点没放灯,为1代表放灯,f为-1代表根节点
26 {
27     if(vis[i][j])return ans[i][j];
28     vis[i][j]=1;
29     int k,&Ans=ans[i][j],ans0=0;
30     Ans=0;
31     for(k=first[i];~k;k=Next[k])
32     {
33         if(U[k]==f)continue;
34         Ans+=dfs(U[k],1,i);//放灯
35     }
36     Ans+=M;
37     if(~f)
38     {
39         if(j)ans0++;
40         else Ans++;
41     }
42     if(j||f==-1)
43     {
44         for(k=first[i];~k;k=Next[k])
45         {
46             if(U[k]==f)continue;
47             ans0+=dfs(U[k],0,i); //不放灯
48         }
49         Ans=min(Ans,ans0);
50     }
51     return Ans;
52 }
53 int main()
54 {
55     int T;
56     scanf("%d",&T);
57     int i,u,v;
58     while(T--)
59     {
60         cnt=0;
61         memset(vis,0,sizeof(vis));
62         memset(first,-1,sizeof(first));
63         scanf("%d%d",&n,&m);
64         for(i=0;i<m;i++)
65         {
66             scanf("%d%d",&u,&v);
67             add(u,v);
68         }
69         int Ans=0;
70         for(i=0;i<n;i++)
71         {
72             if(!vis[i][0])
73                 Ans+=dfs(i,0,-1);
74         }
75         printf("%d %d %d\n",Ans>>11,m-(Ans&(M-1)),Ans&(M-1));//Ans/M,m-Ans%M,Ans%M
76     }
77 }

 

posted @ 2014-01-29 01:23  czjxy881  阅读(190)  评论(0编辑  收藏  举报