LightOj 1230 Placing Lampposts(树形DP)

题意:给定一个森林。每个节点上安装一个灯可以覆盖与该节点相连的所有边。选择最少的节点数num覆盖所有的边。在num最小的前提下,合理放置num个灯使得被两个灯覆盖的边最多?

思路:F[i][0]代表没放灯,F[i][1]代表放了灯,G[i]类似。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 int f[1005][2],g[1005][2];
 7 int tot,go[200005],first[200005],next[200005];
 8 int n,m;
 9 int read(){
10     char ch=getchar();int t=0,f=1;
11     while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();}
12     while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
13     return t*f;
14 }
15 void insert(int x,int y){
16     tot++;
17     go[tot]=y;
18     next[tot]=first[x];
19     first[x]=tot;
20 }
21 void add(int x,int y){
22     insert(x,y);insert(y,x);
23 }
24 void dfs(int x,int fa){
25     f[x][0]=0;g[x][0]=0;
26     f[x][1]=1;g[x][1]=0;
27     for (int i=first[x];i;i=next[i]){
28         int pur=go[i];
29         if (pur==fa) continue;
30         dfs(pur,x);
31         if (f[pur][0]<f[pur][1]||(f[pur][0]==f[pur][1]&&g[pur][0]>g[pur][1]+1)){
32             f[x][1]+=f[pur][0];
33             g[x][1]+=g[pur][0];
34         }else{
35             f[x][1]+=f[pur][1];
36             g[x][1]+=g[pur][1]+1;
37         }
38         f[x][0]+=f[pur][1];
39         g[x][0]+=g[pur][1];
40     }
41 }
42 int main(){
43     int T;
44     scanf("%d",&T);
45     for (int Tcase=1;Tcase<=T;Tcase++){
46         n=read();m=read();
47         tot=0;
48         for (int i=1;i<=n;i++) first[i]=g[i][0]=g[i][1]=0,f[i][0]=f[i][1]=-1;
49         for (int i=1;i<=m;i++){
50             int x=read(),y=read();
51             x++;y++;
52             add(x,y);
53         }
54         int ans1=0,ans2=0;
55         for (int i=1;i<=n;i++)
56          if (f[i][0]==-1&&f[i][1]==-1){
57             dfs(i,0);
58             if (f[i][0]<f[i][1]||(f[i][0]==f[i][1]&&g[i][0]>g[i][1])){
59                 ans1+=f[i][0];
60                 ans2+=g[i][0];
61             }else{
62                 ans1+=f[i][1];
63                 ans2+=g[i][1];
64             }
65          }
66         printf("Case %d: %d %d %d\n",Tcase,ans1,ans2,m-ans2);
67     }
68 }
时间: 2024-11-06 13:48:53

LightOj 1230 Placing Lampposts(树形DP)的相关文章

UVA 10859 - Placing Lampposts 树形DP、取双优值

                          Placing Lampposts As a part of the mission ‘Beauti?cation of Dhaka City’, the government has decided to replace all theold lampposts with new expensive ones. Since the new ones are quite expensive and the budget is notup to

UVA 10859 Placing Lampposts 树形dp(水

题目链接:点击打开链接 题意: 白书P70 思路: 简单题,每个点分放或不放. import java.io.PrintWriter; import java.util.ArrayList; import java.util.Scanner; public class Main { int min(int a,int b){return a>b?b:a;} int max(int a,int b){return a>b?a:b;} static int N = 1005; static int

UVA 10859 Placing Lampposts 树形DP

dfs+记忆化搜索,白书上给了一种很神的存答案的方式,要同时保存两个值,可以将一个值乘以一个大整数加上另外一个. 具体状态转移见注释 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queue>

LightOJ1230 Placing Lampposts(DP)

题目大概说给一个森林求其最小点覆盖数,同时在最小点覆盖条件下输出最多有多少条边被覆盖两次. dp[0/1][u]表示以u为根的子树内的边都被覆盖且u不属于/属于覆盖集所需的最少点数 另外,用cnt[0/1][u]表示满足dp[0/1][u]状态下子树内被覆盖两次最多的边数 对于dp[0][u]只能从其孩子结点v的dp[1][v]转移,而dp[1][u]从dp[0][v]或者dp[1][v]转移,转移时如果同时转移更新cnt的值.. 思路要清晰..转移细节要注意..另外注意是森林. 1 #incl

uva 10859 Placing Lampposts,树形dp

// uva 10859 Placing Lampposts // 树形dp // // 题目的意思是一个无向无环图中,有一些顶点和一些边 // 要在顶点上放置灯笼(灯笼可以照亮与它相邻接的点), // 使得所有的边都能被灯笼照亮,其中可能有一些边被两个灯笼 // 照亮,则要求使得所有边都被灯笼照亮所需灯笼的最小值, // 并且,此时边同时被两个灯笼照亮的数目应尽可能的多 // // 思路是 // d[i][0]表示在节点i不放置灯笼所需的灯笼的最小值 // d[i][1]表示在节点i放置灯笼所

Placing Lampposts - UVa 10859 树形dp

As a part of the mission ?Beautification of Dhaka City?, the government has decided to replace all the old lampposts with new expensive ones. Since the new ones are quite expensive and the budget is not up to the requirement, the government has decid

lightoj 1201 - A Perfect Murder(树形dp)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1201 题解:简单的树形dp,dp[0][i]表示以i为根结点不傻i的最多有多少dp[0][i]+=max(dp[0][j],dp[1][i]),dp[1][i]表示i傻的最多有多少dp[1][i]+=dp[0][j]. 注意这些点不一定是全联通的. #include <iostream> #include <cstring> #include <cstdi

UVA 10859 Placing Lampposts(树DP)

题意:给一个n个顶点m条边的无向无环图,在尽量少的结点上放灯,使得所有边都被照亮.每盏灯将照亮以它为一个端点的所有边.在灯的总数最小的前提下,被两盏灯同时照亮的变数应该尽量大. 思路:无向无环图就是"森林",常用树形dp,本题要优化的目标有两个,放置的灯数a应尽量少,被两盏灯同时照亮的边数b应尽量大,为了统一,我们把b替换成"恰好被一盏灯照亮的边数c尽量小".然后设x=Ma+c为最终的优化目标,M是一个很大的正整数.当x取最小值的时候,x/M就是a的最小值,x%M就

HDU-2196 Computer (树形DP)

最近在看树形DP,这题应该是树形DP的经典题了,写完以后还是有点感觉的.之后看了discuss可以用树分治来做,以后再试一试. 题目大意 找到带权树上离每个点的最远点.︿( ̄︶ ̄)︿ 题解: 对于每一个点的最远点,就是以这个点为根到所有叶子节点的最长距离.但是如果确定根的话,除了根节点外,只能找到每个节点(度数-1)个子树的最大值,剩下一个子树是该节点当前的父亲节点. 所以当前节点的最远点在当前节点子树的所有叶子节点以及父亲节点的最远点上(当父亲节点的最远点不在当前节点的子树上时), 如果父亲节