poj3659

/*
poj3659
树的最小支配集
树状DP
by xjy*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=10000+100;
struct node//链式前向星存图
{
    int to;
    int next;
};
node edge[2*maxn];//因为无向,所以同一条边会存两次
bool vis[maxn];
int head[maxn];
int dp[maxn][3];//状态,对于树上的任意一个点,其合法状态有三种,被自身覆盖,被父节点覆盖,被子节点覆盖
int n;
int tot;
const int inf=0xfffff;
void add(int x,int y)
{
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot++;//记录该点这次出现的边的位置
}
void dfs(int nod)
{
    bool flag=true;//在对dp[nod][1]的处理上要用到
    dp[nod][0]=1,dp[nod][1]=dp[nod][2]=0;//初始化
    vis[nod]=true;
    int Min=inf;
    int v;
    for(int i=head[nod];i!=-1;i=edge[nod].next)
    {
        v=edge[i].to;
        if(!vis[v])
        {
            dfs(v);
            dp[nod][0]+=min(dp[v][0],min(dp[v][1],dp[v][2]));
            dp[nod][2]+=min(dp[v][0],dp[v][1]);
            if(dp[v][0]<=dp[v][1])
            {
                flag=false;
                dp[nod][1]+=dp[v][0];
            }
            else
            {
                dp[nod][1]+=dp[v][1];
                Min=min(Min,dp[v][0]-dp[v][1]);
            }
        }
    }
    if(flag) //所有子节点都没有放置,不合题意,选择最优的进行放置
        dp[nod][1]+=Min;//对于叶子节点,dp[i][1]=inf:
}
void init()
{
    int a,b;
    memset(head,-1,sizeof(head));
    memset(vis,false,sizeof(vis));
    tot=1;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
    }
}
int main()
{
     while(scanf("%d",&n)!=EOF)
     {
         init();
         dfs(2);
         printf("%d\n",min(dp[2][0],dp[2][1]));//选1作为整个树的根节点,不可能出现其被其父节点覆盖的情况
     }
    return 0;
}

时间: 2024-10-10 11:11:24

poj3659的相关文章

10.22~10.28一周经典题目整理(meeting,BZOJ4377,POJ3659)

meeting:给正n边形每个点染上黑色或者白色,问有多少个同色的等腰三角形. 以正五边形为例这里将最上面的点作为顶点,得到若干对相等的腰 ,注意到以最上面的点作为顶点的等腰三角形的个数,等于颜色相等且都为顶点颜色的对称点的个数. O(n^2)统计即可. PS:注意减去等边三角形的情况. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cstdlib> 5

【POJ3659】【USACO 2008 Jan Gold】 3.Cell Phone Network 树上最小支配集/贪心 两种做法

题意:求树上最小支配集 最小支配集:点集,即每个点可以"支配"到相邻点,求最少点数可以使所有点被支配. 图上的最小支配集是NP的,但是树上的可以DP做,是O(n)的. 暴力做就好了, f[i]表示此 点被选时的子树全支配的最小代价 g[i]表示其父亲节 点被选时的子树全支配的最小代价 h[i]表示其某子节 点被选时的子树全支配的最小代价 然后暴力转移. (v是子节点) f[x]=∑(min(f[v],min(g[v],h[v])))+1; g[x]=∑(min(f[v],h[v]));

POJ3659 Cell Phone Network(树上最小支配集:树型DP)

题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. 树上的每个结点作为其子树的根可以有三个状态: 不属于支配集且还没被支配 不属于支配集但被其孩子支配 属于支配集 那么就是用dp[u][1\2\3]来表示动归的状态. 123转移该怎么转移就怎么转移..最后的结果就是min(dp[root][2],dp[root][3]). 要注意的是对于有些结点前2

POJ3659 Cell Phone Network【最小支配集】【贪心】

Cell Phone Network Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5735Accepted: 2053 Description Farmer John has decided to give each of his cows a cell phone in hopes to encourage their social interaction. This, however, requires him to

POJ3659 [usaco2008jan_gold]电话网络

校内OJ上的题,刚开始做的时候以为是道SB题10分钟就能搞完.. 然后准备敲了才发现自己是个SB.. 刚开始以为是个很裸的TreeDP,然后就只设了两个状态,但是怎么想怎么不对.复杂度好像要爆炸.改成左儿子右兄弟好像根本无法转移.. 搜了搜题解,发现不用改成左儿子右兄弟,把两个状态改成三个状态就行了 $f[node][0]$ 在$node$节点的子树被覆盖且$node$被建立 $f[node][1]$ 在$node$节点的子树被覆盖且$node$未被建立 $f[node][2]$ 在$node$

poj3659 Cell Phone Network(最小支配集-树形dp)

题目链接:点击打开链接 题目描述:给定一棵树,从中选取尽量少的点使每个点要么被选中,要么和被选中的点直接相连? 解题思路:树上的最小支配集,树形dp dp[i][0]:选中i作为支配集 dp[i][1]:不选i作为支配集,但其子节点覆盖了i dp[i][2]:不选i作为支配集,而且其子节点没有覆盖i 代码: #pragma comment(linker,"/STACK:1024000000,1024000000") #include <cstdio> #include &l