【Uva 12093】Protecting Zonk

Link:

Description

n个节点的树;
每个节点都可以选择3种
1.覆盖和它相连的边; c1花费;
2.覆盖和它相连的边以及和它相连的点相连的边; c2花费;
3.不进行操作
覆盖所有的边的最小花费;

Solution

/*
    n个节点的树;
    每个节点都可以选择两种
        1.覆盖和它相连的边; c1花费;
        2.覆盖和它相连的边以及和它相连的点相连的边; c2花费;
    覆盖所有的边的花费;

    g[i][3]表示i节点以下的边都被覆盖的最小花费,i不放,上面一条边有没有被覆盖,
        0没,1有
        2表示i可能和它的子树有一个没连上,i不放的最小花费(当然此时i上面没有边);
        {多定义g[i][2]这个状态,是因为可能i节点放了个2,然后{儿子的儿子}和{儿子}没连;
         这时在i放一个2也是可以的}
    f[i][1]...,i放一个1
    f[i][2]...,i放一个2
    叶子节点i
        g[i][0] = 0,g[i][1] = INF,f[i][1] = c1,f[i][2] = c2;
    非叶子节点i
        g[i][0]
            每个子树sonj;
                {
                    g[sonj][1];f[sonj][1];
                }
        g[i][1]
            每个子树sonj
                {
                    //肯定要一个f[][2]则其他所有儿子都能连上了
                    tmep1 = min(f[sonj][1],f[sonj][2],g[sonj][1],g[sonj][0]);
                    min{f[sonj][2]-temp1}

                }

        g[i][2] -- i可能和它的子树有一个没连上?
        {
            {g[sonj][0..1],f[sonj][1],f[sonj][2]}
        }

        f[i][1]
            每个子树sonj
                {
                    {g[sonj][0..1],f[sonj][1],f[sonj][2]} + c1
                }

        f[i][2]
            每个子树sonj
                {
                    {g[sonj][0..2],f[sonj][1],f[sonj][2]} + c2;
                }
*/


NumberOf WA

0

Reviw

树形DP多想想,感觉不是那么难.

Code

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)
#define ri(x) scanf("%d",&x)
#define rl(x) scanf("%lld",&x)
#define rs(x) scanf("%s",x+1)
#define oi(x) printf("%d",x)
#define ol(x) printf("%lld",x)
#define oc putchar(' ')
#define all(x) x.begin(),x.end()
#define Open() freopen("F:\\rush.txt","r",stdin)
#define Close() ios::sync_with_stdio(0)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1e4;
const int INF = 0x3f3f3f3f;

int n,c1,c2,g[N+10][3],f[N+10][3];
vector <int> G[N+10];

void dfs(int x,int fa){
    if (x!=1 && (int) G[x].size()==1){
        g[x][0] = 0,g[x][1] = INF,f[x][1] = c1,f[x][2] = c2;
        g[x][2] = INF;
        return;
    }

    int len = G[x].size();
    g[x][0] = 0;
    rep1(i,0,len-1){
        int y = G[x][i];
        if (y==fa) continue;
        dfs(y,x);
        g[x][0] += min(g[y][1],f[y][1]);
    }

    g[x][1] = 0;int t = INF;
    f[x][1] = c1,f[x][2] = c2,g[x][2] = 0;
    rep1(i,0,len-1){
        int y = G[x][i],temp1;
        if (y==fa) continue;
        temp1 = min(f[y][1],f[y][2]);
        temp1 = min(temp1,g[y][1]);
        temp1 = min(temp1,g[y][0]);
        g[x][1] += temp1;
        t = min(t,f[y][2]-temp1);
        f[x][1] += temp1;
        g[x][2] += temp1;
        temp1 = min(temp1,g[y][2]);
        f[x][2] += temp1;
    }
    g[x][1] += t;
}

int main(){
    //Open();
    //Close();
    while (~ri(n)){
        ri(c1),ri(c2);
        if (n==0) break;
        rep1(i,1,n) G[i].clear();
        rep1(i,1,n-1){
            int x,y;
            ri(x),ri(y);
            G[x].pb(y),G[y].pb(x);
        }

        dfs(1,0);
        int ans = min(g[1][0],g[1][1]);
        ans = min(ans,f[1][1]),ans = min(ans,f[1][2]);
        oi(ans);puts("");
    }
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(144)  评论(0编辑  收藏  举报