zoukankan      html  css  js  c++  java
  • UVa10895 Placing Lampposts

    UVa10895 Placing Lampposts

    链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34290

    【思路】

       树上DP+双重优化目标。

       本题的特点就是有两个优化目标分别为:在尽量少的结点放灯、在此前提下有被两盏灯照亮的边最多。

       首先进行转化:将第二个优化目标转化为在此前提下被一盏灯照亮的边最少。这样两个优化目标就都是求最小值。用一个hash(A,B)将两个新的优化目标AB映射到一个整数,转化为求这个整数的最小值,可以定义hash=A*M+B完成这个功能,M是一个较大数。

       树上DP。设d[i][j]表示以i为根的子树且有父节点状态为j时的最优值,注意用j记录父节点状态。有如下转移式:

          略。详见代码。

    【代码】

     1 #include<iostream>
     2 #include<cstring>
     3 #include<vector>
     4 using namespace std;
     5 
     6 const int maxn = 1000+10;
     7 const int INF=1<<30;
     8 const int M=2000;
     9 
    10 vector<int> G[maxn];
    11 int d[maxn][2];
    12 bool vis[maxn][2];
    13 int n,m; 
    14 
    15 inline void init() {
    16     for(int i=0;i<n;i++) G[i].clear();
    17     memset(vis,false,sizeof(vis));
    18     memset(d,0,sizeof(d)); 
    19 }
    20 
    21 int dp(int i,int j,int fa) {
    22     if(vis[i][j]) return d[i][j];
    23     vis[i][j]=true;
    24     int &ans=d[i][j];
    25     
    26     //无论j都可以在i上放置街灯 
    27     ans=M;              //放置一个街灯的价值 
    28     for(int k=0;k<G[i].size();k++) {
    29         int v=G[i][k];
    30         if(v!=fa) {
    31             ans += dp(v,1,i);
    32         }
    33     }
    34     if(!j && fa>=0) ans++;  //01
    35     
    36     if(j || fa<0)  //根也可以不放 
    37     {
    38         int sum=0;
    39         for(int k=0;k<G[i].size();k++) {
    40            int v=G[i][k];
    41            if(v!=fa) {
    42               sum += dp(v,0,i);
    43            }
    44         }
    45         if(fa>=0) sum++;             //10 //根不算 
    46         ans=min(ans,sum);  //两种情况取min 
    47     }
    48     
    49     return ans;
    50 }
    51 
    52 int main() {
    53     ios::sync_with_stdio(false);
    54     int T; cin>>T;
    55     while(T--)
    56     {
    57         cin>>n>>m;
    58         init();
    59         int u,v;
    60         for(int i=0;i<m;i++) {
    61             cin>>u>>v;
    62             G[u].push_back(v);
    63             G[v].push_back(u);
    64        }
    65        int ans=0;
    66        for(int i=0;i<n;i++) if(!vis[i][0]) {
    67                ans += dp(i,0,-1);
    68        }
    69        cout<<ans/M<<" "<<m-ans%M<<" "<<ans%M<<"
    ";
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    Educational Codeforces Round 67 D. Subarray Sorting
    2019 Multi-University Training Contest 5
    Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code
    Educational Codeforces Round 69 D. Yet Another Subarray Problem
    2019牛客暑期多校训练第六场
    Educational Codeforces Round 68 E. Count The Rectangles
    2019牛客多校第五场题解
    2019 Multi-University Training Contest 3
    2019 Multi-University Training Contest 2
    [模板] 三维偏序
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4896138.html
Copyright © 2011-2022 走看看