zoukankan      html  css  js  c++  java
  • luogu P2700 逐个击破

    嘟嘟嘟

    这道题只要树形dp做的熟练的话就能秒(显然我不能)。

    令dp[u][0 / 1]表示u所在的子树和u相连的联通块没有/有敌人的最少代价。而且按题中所述,这个联通块只能有1个敌人。

    分情况:

    若敌人在节点u:

    则dp[u][0] = INF,dp[u][1] = Σmin{dp[v][0], dp[v][1] + w[i]}。

    若敌人不在u:

    则dp[u][0] = Σmin{dp[v][0], dp[v][1] + w[i]}, dp[u][1] = Σmin{dp[v][0], dp[v][1] + w[i]} + dp[v'][1]。(v'∉{v})

    只要一直记着一个联通块最多只能有一个敌人就行了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const ll INF = 1e12;
    19 const db eps = 1e-8;
    20 const int maxn = 1e5 + 5;
    21 inline ll read()
    22 {
    23   ll ans = 0;
    24   char ch = getchar(), last = ' ';
    25   while(!isdigit(ch)) last = ch, ch = getchar();
    26   while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    27   if(last == '-') ans = -ans;
    28   return ans;
    29 }
    30 inline void write(ll x)
    31 {
    32   if(x < 0) x = -x, putchar('-');
    33   if(x >= 10) write(x / 10);
    34   putchar(x % 10 + '0');
    35 }
    36 
    37 int n, k;
    38 bool vis[maxn], in[maxn];
    39 
    40 struct Edge
    41 {
    42   int nxt, to, w;
    43 }e[maxn << 1];
    44 int head[maxn], ecnt = -1;
    45 void addEdge(int x, int y, int w)
    46 {
    47   e[++ecnt] = (Edge){head[x], y , w};
    48   head[x] = ecnt;
    49 }
    50 
    51 ll dp[maxn][2];
    52 void dfs(int now, int _f)
    53 {
    54   if(vis[now]) dp[now][0] = INF;
    55   in[now] = vis[now];
    56   ll sum = 0;
    57   for(int i = head[now], v; i != -1; i = e[i].nxt)
    58     {
    59       v = e[i].to;
    60       if(v == _f) continue;
    61       dfs(v, now);
    62       in[now] |= in[v];
    63       sum += min(dp[v][0], dp[v][1] + e[i].w);
    64     }
    65   if(vis[now]) dp[now][1] = sum;
    66   else dp[now][0] = dp[now][1] = sum;
    67   if(!vis[now]) for(int i = head[now], v; i != -1; i = e[i].nxt)
    68     {
    69       v = e[i].to;
    70       if(v == _f || !in[v]) continue;
    71       dp[now][1] = min(dp[now][1], sum - min(dp[v][0], dp[v][1] + e[i].w) + dp[v][1]);
    72     }
    73 }
    74 
    75 int main()
    76 {
    77   Mem(head, -1);
    78   n = read(); k = read();
    79   for(int i = 1; i <= k; ++i) {int x = read() + 1; vis[x] = 1;}
    80   for(int i = 1; i < n; ++i)
    81     {
    82       int x = read() + 1, y = read() + 1, w = read();
    83       addEdge(x, y, w); addEdge(y, x, w);
    84     }
    85   dfs(1, 0);
    86   write(min(dp[1][0], dp[1][1])), enter;
    87   return 0;
    88 }
    View Code
  • 相关阅读:
    Intent
    What should we do next in general after collecting relevant data
    NOTE FOR Secure Friend Discovery in Mobile Social Networks
    missing pcap.h
    after building Android Source code
    plot point(one column)
    When talking to someone else, don't infer that is has been talked with others at first. It may bring repulsion to the person who is talking with you.
    进程基本知识
    Python input和raw_input的区别
    强制 code review:reviewboard+svn 的方案
  • 原文地址:https://www.cnblogs.com/mrclr/p/9910047.html
Copyright © 2011-2022 走看看