UVA10859 Placing Lampposts

Placing Lampposts

 给你一个森林。选择一些点放灯,每个灯可以照亮所在点周围的所有边。优先最小化灯的数量,使所有边被照亮,然后最大化被两盏灯照亮的边的个数

 

由于   被两盏灯照亮的边的个数 + 被一盏灯照亮的边的个数 = 边数

把“最大化被两盏灯照亮的边的个数”转换为“最小化被一盏灯照亮的边的个数

 

“若有两个变量v1,v2,最优化v1的前提下最优化v2,可以设置为最优化Mv1 + v2,M是一个比max(v2) - min(v2)大的数”.这样的话v1增加1,增加量就一定比v2增加量大了

 

然后常规树形dp即可

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 #include <queue>
 7 #include <vector>
 8 #define min(a, b) ((a) < (b) ? (a) : (b))
 9 #define max(a, b) ((a) > (b) ? (a) : (b))
10 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
11 inline void swap(int &a, int &b)
12 {
13     int tmp = a;a = b;b = tmp;
14 }
15 inline void read(int &x)
16 {
17     x = 0;char ch = getchar(), c = ch;
18     while(ch < '0' || ch > '9') c = ch, ch = getchar();
19     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
20     if(c == '-') x = -x;
21 }
22 
23 const int INF = 0x3f3f3f3f;
24 const int MAXN = 10000 + 10;
25 const int K = 2000;
26 
27 struct Edge
28 {
29     int u,v,nxt;
30     Edge(int _u, int _v, int _nxt){u = _u;v = _v;nxt = _nxt;}
31     Edge(){}
32 }edge[MAXN << 1];
33 int head[MAXN], cnt;
34 inline void insert(int a, int b)
35 {
36     edge[++cnt] = Edge(a,b,head[a]);
37     head[a] = cnt;
38 }
39 
40 int t,n,m,b[MAXN],ans,dp[MAXN][2],root;
41 
42 //设x为被一盏灯照亮的边,y表示灯的数量,最小化Ky + x 
43 //dp[i][0]表示第i个点的父亲不放灯,i子树中的边和i与父亲的边最小Ky + x
44 //dp[i][1]表示第i个点的父亲放灯,i子树中的边和i与父亲的边最小的Ky + x
45 
46 void dfs(int x)
47 {
48     b[x] = 1;
49     int tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0;
50     for(register int pos = head[x];pos;pos = edge[pos].nxt)
51     {
52         int v = edge[pos].v;
53         if(!b[v]) dfs(v);
54         
55         //dp[x][0]父节点不放灯 
56         //这个点不放灯 
57         if(root == x) tmp1 += dp[v][0];
58         //这个点放灯
59         tmp2 += dp[v][1];
60         
61         //dp[x][1]父节点放灯 
62         //这个点不放灯
63         tmp3 += dp[v][0]; 
64         //这个点放灯 
65         tmp4 += dp[v][1];
66     } 
67     tmp2 += K;tmp4 += K;
68     if(root != x) ++ tmp2, ++ tmp3, tmp1 = INF;
69     dp[x][0] = min(tmp1, tmp2);
70     dp[x][1] = min(tmp3, tmp4);
71     return;
72 } 
73 
74 int main()
75 {
76     read(t);
77     for(;t;--t)
78     {
79         read(n), read(m);
80         memset(b, 0, sizeof(b));
81         memset(head, 0, sizeof(head));
82         memset(dp, 0, sizeof(dp));ans = 0; 
83         for(register int i = 1;i <= m;++ i)
84         {
85             int tmp1,tmp2;read(tmp1), read(tmp2);
86             ++ tmp1, ++ tmp2;
87             insert(tmp1, tmp2), insert(tmp2, tmp1);
88         }
89         for(register int i = 1;i <= n;++ i)
90             if(!b[i]) root = i, dfs(i), ans += dp[i][0];
91          printf("%d %d %d\n", ans/K, m - ans%K, ans%K);
92     }
93     return 0;
94 }
UVA10859

 

posted @ 2018-01-17 09:13  嘒彼小星  阅读(241)  评论(0编辑  收藏  举报