POJ 1463 && HDU 1054 Strategic Game (树形DP)

每个节点上可以站士兵守卫道路。

问要守卫所有的道路至少要多少个士兵。


跟那个 

poj 2342 Anniversary party(简单树形dp+dfs)

真是像极了。。。

我就是根据那个来写的。。。


思路如下:

如果当前节点站士兵,则以它为父亲的子节点(就是它的邻接点)就可以站或者不站,取

两种情况中消耗最小的。 dp[i][1]+=min(dp[v][1],dp[v][0])

如果当前节点不站士兵,则它的邻接点不能被守卫到,故它的邻接点必须要有士兵。

dp[i][0]+=dp[v][1];

v是i的邻接点。


吐槽一下啦+ +

hdu 数据比poj 弱。。。。我开始用vector写,poj 上死活都是mle

后来看了别人的提醒,改成邻接表存,就AC了。。。

加边的时候当无向边处理。所以不要忘了add(b,a)!!


邻接表版本yoha !

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;

struct edge
{
    int to;
    int next;
}w[10010];
bool vis[1510];
int dp[1510][2],head[1510],tot;

void add(int x,int y)
{
    w[tot].to=y;
    w[tot].next=head[x];
    head[x]=tot++;
}

void dfs(int r)
{
    vis[r]=true;
    int v,i;
    for(i=head[r];i;i=w[i].next)
    {
        v=w[i].to;
        if(!vis[v])
        {
            dfs(v);
            dp[r][0]+=dp[v][1];
            dp[r][1]+=min(dp[v][1],dp[v][0]);
        }
    }
}

int main()
{
    int n,m,a,b;
    while(scanf("%d",&n)!=EOF)
    {
        memset(vis,0,sizeof(vis));
        memset(head,0,sizeof(head));
        tot=1;

        for(int i=0;i<n;i++)
        {
            dp[i][0]=0;
            dp[i][1]=1;
        }
        for(int i=0;i<n;i++)
        {
            scanf("%d:(%d)",&a,&m);
            for(int i=0;i<m;i++)
            {
                scanf("%d",&b);
                add(a,b);
                add(b,a);
            }
        }
        dfs(0);
        printf("%d\n",min(dp[0][0],dp[0][1]));
    }
    return 0;
}

只在hdu过的了的vector版本~~~~~= =

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;

vector<int> t[1510];
bool vis[1510];
int dp[1510][2];

void dfs(int r)
{
    vis[r]=true;
    int v;
    int s=t[r].size();
    for(int i=0;i<s;i++)
    {
        v=t[r][i];
        if(!vis[v])
        {
            dfs(v);
            dp[r][0]+=dp[v][1];
            dp[r][1]+=min(dp[v][1],dp[v][0]);
        }
    }
    //dp[r][1]+=1;
}

int main()
{
    int n,m,a,b;
    while(scanf("%d",&n)!=EOF)
    {
        memset(t,0,sizeof(t));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            t[i].clear();

        for(int i=0;i<n;i++)
        {
            dp[i][0]=0;
            dp[i][1]=1;
        }
        //memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++)
        {
            scanf("%d:(%d)",&a,&m);
            for(int i=0;i<m;i++)
            {
                scanf("%d",&b);
                t[a].push_back(b);
                t[b].push_back(a);
            }
        }
        dfs(0);
        printf("%d\n",min(dp[0][0],dp[0][1]));
    }
    return 0;
}



POJ 1463 && HDU 1054 Strategic Game (树形DP)

上一篇:EasyHook库系列使用教程之一写在之前


下一篇:静态库的编写