ACM: 动态规划题 bnu 13149

来源:互联网 发布:服务器端语言编程 编辑:程序博客网 时间:2024/06/10 07:36

Placing Lampposts

Description

As a part of the mission 'Beautification of Dhaka City', thegovernment has decided to replace all the old lampposts with newexpensive ones. Since the new ones are quite expensive and thebudget is not up to the requirement, the government has decided tobuy the minimum number of lampposts required to light the wholecity.

Dhaka city can be modeled as an undirected graph with no cycles,multi-edges or loops. There are several roads and junctions. Alamppost can only be placed on junctions. These lampposts can emitlight in all the directions and that means a lamppost that isplaced in a junction will light all the roads leading away fromit.

The 'Dhaka City Corporation' has given you the road map of Dhakacity. You are hired to find the minimum number of lampposts thatwill be required to light the whole city. These lampposts can thenbe placed on the required junctions to provide the service. Therecould be many combinations of placing these lampposts that willstill cover all the roads. In that case, you have to place them insuch a way so that the number of roads receiving light from twolampposts is maximized. (A careful thought will reveal that all theroads will get light either from one post or two posts).


Input

Input starts with an integer T (≤ 30), denotingthe number of test cases.

Each case starts with a blank line. The next line contains twointegers N (1 ≤ N ≤ 1000) and M (0 ≤ M <N) which indicate the number of junctions and roadsrespectively. The junctions are numbered from 0 toN-1. Each of the next M lines contains two integersa and b (0 ≤ a, b < N, a ≠ b), whichdenotes that there is a road from junction a tob.


Output

For each case, print the case number, the minimum number oflampposts required to light the whole city, the number of roadsthat are receiving lights from two lampposts and the number ofroads 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

Case 1: 2 1 2

Case 2: 1 0 4

 

题意: 城市规划, 在n个路灯节点, m条道路, 现在要使用最少的路灯放置在路灯节点上, 使得被2盏路灯

      照亮的道路尽可能多,只被一盏路灯照亮尽可能少. 输出路灯数, 2盏灯照亮的路和1盏灯照亮的路.

 

解题思路:

    1. 其实总共的道路的数量一定的, 只要考虑1盏灯的路尽可能少, 那么2盏灯照亮的路就多了, 这题

       状态很明显, dp[i][j]: i的父亲节点状态为j时(j == 0没有放置路灯, j == 1放置路灯), 并且

       以i为当前子树根的最小"满足条件值"(稍后讨论)包括了节点i与其父亲节点的边.

       状态方程:

       (1). 当前子树根i不放置路灯, 条件是j == 1 || i是树的根节点;

            dp[i][0] += dp[i的子节点][1];

            最后如果节点i的父亲节点不是树的根节点最后还需要加上一条边.

       (2). 当前子树根i放置路灯;

             dp[i][1]+= dp[i的子节点][1];

            最后如果j == 0 &&父亲节点不是树根那么还需要加上一条边.

     2.这里需要讨论一个问题, 加上2个值需要优化, v1和v2, 在满足v1最小的前提下, 当相同情况下,

       才需要讨论v2最小的时候, 可以把它们变成一个值设x = M*v1+v2; 其中M是v2的理论最大值与

        v2的理论最小值得差,很明显当v1不相同的时候, v2的值不会影响到结果的选择, 相当于v1占

       比重大; 当v1相同时, 才需要讨论v2的结果. 这样做的好处是将2个需要优化的值, 变成一个

       值计算, v1 = x/M, v2 = x%M即可.(好方法!!!)

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
#define MAX 1005
#define M 2000

int n, m;
int dp[MAX][2];
vector g[MAX];

inline int min(int a, int b)
{
 return a < b ? a : b;
}

void readGraph()
{
 memset(dp, -1, sizeof(dp));
 for(int i = 0; i < n; ++i)
  g[i].clear();
 int u, v;
 for(int j = 0; j < m; ++j)
 {
  scanf("%d %d",&u, &v);
  g[u].push_back(v);
  g[v].push_back(u);
 }
}

int DP(int i, int j, int fa)
{
 if(dp[i][j] != -1) return dp[i][j];

 int ans = M;
 for(int k = 0; k < g[i].size();++k)
 {
  if(g[i][k] != fa)
   ans +=DP(g[i][k], 1, i);
 }
 if(j == 0 && fa!= -1) ans += 1;

 if(j == 1 || fa == -1)
 {
  int ans2 = 0;
  for(int k = 0; k< g[i].size(); ++k)
   if(g[i][k] !=fa)
    ans2+= DP(g[i][k], 0, i);
  if(fa != -1) ans2 += 1;
  ans = min(ans, ans2);
 }
 return dp[i][j] = ans;
}

int main()
{
// freopen("input.txt", "r", stdin);
 int caseNum, num = 1;
 scanf("%d", &caseNum);
 while(caseNum--)
 {
  scanf("%d %d",&n, &m);
  readGraph();

  int result = 0;
  for(int i = 0; i< n; ++i)
  {
   if(dp[i][0]== -1)
    result+= DP(i, 0, -1);
  }

  printf("Case %d: %d %d%d\n", num++, result/M, m-result%M, result%M);
 }
 return 0;
}

0 0