zoukankan      html  css  js  c++  java
  • SDOI 2006

    最小监视覆盖,即选中费用最小的i个点来选中一些边,这些边把所有的点覆盖。

    #include <cstdio>
    using namespace std;
    
    #define MAXV    1505
    #define MAXE    (MAXV - 1)
    int Vefw[MAXE], Veh[MAXV], Vet[MAXE], Vc[MAXV], Veptr;
    int dp[MAXV][3],dp2[MAXV];
    
    #define min(a,b) ((a)<(b)?(a):(b))
    
    #define addedge(s,t)    do{
        Vefw[Veptr] = Veh[s], Vet[Veptr] = t;    
        Veh[s] = ++Veptr;}while(0)
    
    void solve(int s)
    {
        dp[s][2] = 0, dp[s][1] = Vc[s];
        for(int e = Veh[s]; e; e = Vefw[e]) {
            int t = Vet[--e];
            solve(t);
            dp[s][1] += min(min(dp[t][0], dp[t][1]), dp[t][2]);
            dp[s][2] += min(dp[t][0], dp[t][1]);
        }
        int k;
        dp2[k=s] = 0x3f3f3f3f;
        for(int e1 = Veh[s]; e1; e1 = Vefw[e1]) {
            int t1 = Vet[--e1];
            dp2[t1] = dp[t1][1];
            for(int e2 = Veh[s]; e2; e2 = Vefw[e2]) {
                int t2 = Vet[--e2];
                if (t2 != t1) dp2[t1] += min(dp[t2][0], dp[t2][1]);
            }
            if (dp2[k] > dp2[t1]) k = t1;
        }
        dp[s][0] = dp2[k];
    }
    
    int N;
    
    int main(void)
    {
    //    freopen("sdoi2006_guard.txt", "r", stdin);
        scanf("%d", &N);
        int root = 0;
        for(int i=0; i<N; ++i) {
            int s, k, c;
            scanf("%d%d%d", &s, &k, &c);
            Vc[--s] = k;
            while(c) {
                int t;
                scanf("%d", &t); --t;
                if (t == root) root = s;
                addedge(s, t);
                --c;
            }
        }
        solve(root);
        printf("%d
    ", min(dp[root][0], dp[root][1]));
        return 0;
    }
    Accepted
    988
    0
    C++ 1421 B 2014-05-20 14:36:41
  • 相关阅读:
    将excel里的有效数据提取出来
    基础二
    状态码
    基础(一)
    爬虫页面
    交集,并集,差集,函数
    魔法和运算器
    Java接口
    Java封装
    Java抽象类
  • 原文地址:https://www.cnblogs.com/e0e1e/p/sdoi2006_guard.html
Copyright © 2011-2022 走看看