10_放置街灯(Placing Lampposts,UVa 10859)

时间:2022-03-31 23:47:20

问题来源:刘汝佳《算法竞赛入门经典--训练指南》 P70 例题30:

问题描述:有给你一个n个点m条边(m<n<=1000)的无向无环图,在尽量少的节点上放灯,使得所有边都被照亮,每盏灯将照亮以它为一个端点的所有边。在灯的总数最小的前提下,被两盏灯同时照亮的边数尽量大。

问题分析:1.题中的图,是由多颗树构成的森林,对每颗树用相同的方法即可。

       2.本题优化目标:放置的街灯数a应尽量少,在a尽量少的情况下,被两盏灯同时照亮的边数b尽量大(即只被一盏灯照亮的边数c尽量小(b+c=m)),两个要求可合并为一个要求,即x(x=Ma+c),(要求无论c怎么取值都不会影响a的取值,M是一个比c的最大理论值还要大的数即可)

       3.对于树上的每一个节点i,只有两种状态,放灯和不放灯,i的状态将影响其子节点的决策,则可以将父节点(fa)的状态加入状态表示中,设i点的状态为dp[i][j],其中若j=0表示节点i的父亲节点(fa)没有放灯,若j=1表示fa放灯了:

        决策1:节点i不放灯,必须保证j==1(fa放灯) || i为根节点,此时dp[i][j] = Sum{dp[k][0] | k为取遍i的所有子节点}

             如果i不是根dp[i][j]++(i与fa之间只有一盏灯);

        决策2:节点i放灯,此时dp[i][j] = Sum{dp[k][1] | k为取遍i的所有子节点}+M

             如果j==0 && i不为根节点dp[i][j]++(i与fa之间只有一盏灯);

例题链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1800

例题:UVa 10891

10859 - Placing Lampposts

Time limit: 3.000 seconds

  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 decided to buy the minimum number of lampposts required to light the whole city.
  Dhaka city can be modeled as an undirected graph with no cycles, multi-edges or loops. There are several roads and junctions. A lamppost can only be placed on junctions. These lampposts can emit light in all the directions, and that means a lamppost that is placed in a junction will light all the roads leading away from it.
  The �Dhaka City Corporation� has given you the road map of Dhaka city. You are hired to find the minimum number of lampposts that will be required to light the whole city. These lampposts can then be placed on the required junctions to provide the service. There could be many combinations of placing these lampposts that will cover all the roads. In that case, you have to place them in such a way that the number of roads receiving light from two lampposts is maximized.

Input

  There will be several cases in the input file. The first line of input will contain an integer T(T<=30) that will determine the number of test cases. Each case will start with two integers N(N<=1000) and M( M<N) that will indicate the number of junctions and roads respectively. The junctions are numbered from 0 to N-1. Each of the next M lines will contain two integers a and b, which implies there is a road from junction a to b,
( 0<= a,b < N ) and a != b. There is a blank line separating two consecutive input sets.

Output

  For each line of input, there will be one line of output. Each output line will contain 3 integers, with one space separating two consecutive numbers. The first of these integers will indicate the minimum number of lampposts required to light the whole city. The second integer will be the number of roads that are receiving lights from two lampposts and the third integer will be the number of roads that are receiving light from only one lamppost.

Sample Input

2
4 3
0 1
1 2
2 3

5 4
0 1
0 2
0 3
0 4

Sample Output

2 1 2
1 0 4

代码实现:

 #include "cstdio"
#include "cstring"
#include "vector"
using namespace std; #define N 1005
#define M 2000
int n,m;
int dp[N][]; //对于每个节点,只有两种状态(1:选,0:不选)
int vis[N][]; //标记
vector<int> adj[N]; int inline Min(int a,int b)
{
return a<b?a:b;
} void Init()
{
for(int i=; i<n; i++)
adj[i].clear();
memset(vis,,sizeof(vis));
} int DFS(int i,int j,int fa)
{
if(vis[i][j]) return dp[i][j];
vis[i][j] = ;
int& ans = dp[i][j];
ans = ; //先考虑放灯的情况
for(int k=; k<adj[i].size(); k++)
{
if(adj[i][k]==fa) continue;
ans += DFS(adj[i][k],,i); //在i放灯的情况下,i的子节点放灯的情况
}
if(j== && fa>=) ans++; //父节点没有放灯(j==0) 并且i不为根节点(fa!=-1),则点i和点fa相连的这条边只有一盏灯照亮,ans++;
if(j== || fa<) //i为根节点(fa==-1),或者父亲节点放灯了(j==1),就可以考虑i点不放灯.
{
int sum = ;
for(int k=; k<adj[i].size(); k++)
if(adj[i][k]!=fa)
sum += DFS(adj[i][k],,i);
if(fa>=) sum++; //如果i不是根,则点i和点fa相连的这条边只有一盏灯照亮,sum++;
ans = Min(ans,sum);
}
return ans;
} int main()
{
int T;
int i;
int x,y;
int ans;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
Init();
ans = ;
for(i=; i<=m; i++)
{
scanf("%d %d",&x,&y);
adj[x].push_back(y);
adj[y].push_back(x);
}
for(i=; i<n; i++)
{
if(vis[i][]==) continue;
ans += DFS(i,,-); //i为树根,没有父节点(-1),父节点设为不放灯(0);
}
printf("%d %d %d\n",ans/,m-ans%,ans%);
}
return ;
}

10_放置街灯(Placing Lampposts,UVa 10859)的更多相关文章

  1. UVA - 10859 Placing Lampposts 放置街灯

    Placing Lampposts 传送门:https://vjudge.net/problem/UVA-10859 题目大意:给你一片森林,要求你在一些节点上放上灯,一个点放灯能照亮与之相连的所有的 ...

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

                              Placing Lampposts As a part of the mission ‘Beautification of Dhaka City’, ...

  3. UVa10895 Placing Lampposts

    UVa10895 Placing Lampposts 链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34290 [思路] ...

  4. UVa10859 放置街灯

    Placing Lampposts As a part of the mission �Beautification of Dhaka City�, the government has decide ...

  5. UVa 10859 Placing Lampposts

    这种深层递归的题还是要多多体会,只看一遍是不够的 题意:有一个森林,在若干个节点处放一盏灯,灯能照亮与节点邻接的边.要求:符合要求的放置的灯最少为多少,在灯数最少的前提下,一条边同时被两盏灯照亮的边数 ...

  6. UVa 10859 - Placing Lampposts 树形DP 难度&colon; 2

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  7. uva 10859 - Placing Lampposts dp

    题意: 有n个节点,m条边,无向无环图,求最少点覆盖,并且在同样点数下保证被覆盖两次的变最多 分析: 1.统一化目标,本题需要优化目标有两个,一个最小灯数a,一个最大双覆盖边数b,一大一小,应该归一成 ...

  8. UVA 10859 Placing Lamppost 树形DP&plus;二目标最优解的求解方案

    题意:给定一个无向,无环,无多重边,要求找出最少的若干点,使得,每条边之中至少有一个点上有街灯.在满足上述条件的时候将还需要满足让两个点被选择的边的数量尽量多. 题解: 对于如何求解最小的节点数目这点 ...

  9. UVaLive 10859 Placing Lampposts &lpar;树形DP&rpar;

    题意:给定一个无向无环图,要在一些顶点上放灯使得每条边都能被照亮,问灯的最少数,并且被两盏灯照亮边数尽量多. 析:其实就是一个森林,由于是独立的,所以我们可以单独来看每棵树,dp[i][0] 表示不在 ...

随机推荐

  1. SpringMVC对异常进行全局处理&comma;并区分对待ajax和普通请求

    异常信息应统一进行处理. 程序员开发过程中,应尽量少用try..catch.避免因为catch造成的业务歧义.而在web开发中,普通的页面提交动作,和ajax提交动作,处理方式不一样,因为跳转后直接显 ...

  2. 编程之美--2&period; Trie树 (Trie图)

    #1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助, ...

  3. awk命令简单学习

    请执行命令取出linux中eth0的IP地址(请用cut,有能力者也可分别用awk,sed命令答). 解答: 说明:此题解答方法已经给大家讲解了不下15种,还可以有很多,在这里给大家着重讲下awk的技 ...

  4. BZOJ 1898&colon; &lbrack;Zjoi2004&rsqb;Swamp 沼泽鳄鱼&lpar; dp &plus; 矩阵快速幂 &rpar;

    ----------------------------------------------------------------------- #include<cstdio> #incl ...

  5. Windows在生产体系Android开关机动画

    在Windows根据系统.办Android开关机动画,几个需要注意的问题: 1.压缩的选择 2.压缩的格式: 版权声明:本文博客原创文章,博客,未经同意,不得转载.

  6. sieve的objective-c实现

    用obj-cl来实现前面的sieve代码貌似"丑"了不少,应该有更好的方式:比如不用Foundation或不用NSArray类,而改用其它更"底层"的类. 先把 ...

  7. bzoj 4501 旅行

    01分数规划+最大权闭合子图 倒拓扑序处理每个节点 $$f[x]=\frac{\sum{f[v]}}{n}+1$$ 二分答案$val$ 只需要判断是否存在$\sum{f[v]}+1-val>0$ ...

  8. cf1000C Covered Points Count &lpar;差分&plus;map&rpar;

    考虑如果数字范围没有这么大的话,直接做一个差分数组就可以了 但现在变大了 所以要用一个map来维护 #include<bits/stdc++.h> #define pa pair<i ...

  9. C&num; 开发代码标准

    开发标准文件 文件名称:C#开发规范 版 本:V2.0 前言 目的是为了规范每个人的编程风格,为确保系统源程序可读性,从而增强系统可维护性,制定下述编程规范,以规范系统各部分编程.系统继承的其它资源中 ...

  10. 主成分分析(PCA)原理详解(转载)

    一.PCA简介 1. 相关背景 上完陈恩红老师的<机器学习与知识发现>和季海波老师的<矩阵代数>两门课之后,颇有体会.最近在做主成分分析和奇异值分解方面的项目,所以记录一下心得 ...