[树形DP] poj 3659 Cell Phone Network

来源:互联网 发布:vs软件 编辑:程序博客网 时间:2024/05/17 22:54
最小支配集,求最小的点集覆盖所有的点。
/**[树形DP] poj 3659 Cell Phone Network给定一棵树,求最小支配集dp[i][0] = sum(min(dp[s][2],dp[s][1]))自己没被选,父节点被选中dp[i][1] = sum(min(dp[s][1],dp[s][2]))自己没被选,某儿子结点被选中dp[i][2] = sum(min(dp[s][0],dp[s][1],dp[s][2]))自己被选中求dp[i][1] 时需注意当所有的dp[s][1] < dp[s][2]时是不满足条件的。*/#include <stdio.h>#include <vector>#include <string.h>#include <algorithm>using namespace std;#define N 10001#define INF 100000000vector<int> g[N];int dp[N][3];void dfs(int u,int f){    dp[u][0] = 0;    dp[u][1] = 0;    dp[u][2] = 1;    if(g[u].size() == 1 && g[u][0] == f)    {        dp[u][1] = INF;        return ;    }    int i,flag = 0,minn = INF,dson = 0,v;    for(i = 0; i < g[u].size(); ++i)    {        v = g[u][i];        if(v == f)            continue;        dfs(v,u);        dp[u][2] += min(dp[v][0],min(dp[v][1],dp[v][2]));        dp[u][0] += min(dp[v][2],dp[v][1]);        if(dp[v][1] < dp[v][2])        {            dp[u][1] += dp[v][1];            if(minn > dp[v][2])            {                minn = dp[v][2];                dson = dp[v][1];            }        }        else        {            flag = 1;            dp[u][1] += dp[v][2];        }    }    if(!flag)        dp[u][1] += minn - dson;}int main(){    int n,a,b;    scanf("%d",&n);    --n;    while(n--)    {        scanf("%d%d",&a,&b);        g[a].push_back(b);        g[b].push_back(a);    }    dfs(1,-1);    printf("%d\n",min(dp[1][1],dp[1][2]));    return 0;}

原创粉丝点击