UVA10859 Placing Lampposts(树形DP)

题意:有一个n个点m条边的无向无环图,在尽量少的结点上放灯,使得所有边都被照亮,每栈灯将照亮以它为一个端点的所有边,在灯的总数最小的情况下,被两栈灯同时照亮的情况下边数最大

解法:树形DP(边覆盖)

d[i][0]=0,d[i][1]=1;

d[i][0]=d[j][1];

d[i][1]=min(d[i][0],d[i][1])

cnt[i][0],cnt[i][1]表示节点i放灯和不放灯的情况下边被两栈灯照亮的数量。

// File Name: 10859.cpp
// Author: zlbing
// Created Time: 2013/1/27 16:39:01

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
using namespace std;
#define MAXN 1000+5
vector<int> adj[MAXN];
int n,m;
int d[MAXN][2],cnt[MAXN][2];
bool vis[MAXN];
void dfs(int u)
{
    vis[u]=true;
    d[u][0]=0,d[u][1]=1;cnt[u][0]=cnt[u][1]=0;
    for(int i=0;i<adj[u].size();i++)
    {
        int v=adj[u][i];
        if(!vis[v])
        {
            dfs(v);
            d[u][0]+=d[v][1];
            cnt[u][0]+=cnt[v][1];
            if(d[v][1]==d[v][0])
            {
                d[u][1]+=d[v][1];
                cnt[u][1]+=max(cnt[v][1]+1,cnt[v][0]);
            }
            else if(d[v][1]<d[v][0])
            {
                d[u][1]+=d[v][1];
                cnt[u][1]+=cnt[v][1]+1;
            }
            else
            {
                d[u][1]+=d[v][0];
                cnt[u][1]+=cnt[v][0];
            }
        }
    }
}
int main(){
    int N;
    scanf("%d",&N);
    while(N--)
    {
        scanf("%d%d",&n,&m);
        int a,b;
        for(int i=0;i<n;i++)
            adj[i].clear();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            adj[a].push_back(b);
            adj[b].push_back(a);
        }
        memset(vis,0,sizeof(vis));
        int ans=0,ans1=0;
        for(int i=0;i<n;i++)
            if(!vis[i]){
                dfs(i);
                if(d[i][0]<d[i][1])
                {
                    ans+=d[i][0];
                    ans1+=cnt[i][0];
                }
                else if(d[i][0]==d[i][1])
                {
                    ans+=d[i][0];
                    ans1+=max(cnt[i][0],cnt[i][1]);
                }
                else{
                    ans+=d[i][1];
                    ans1+=cnt[i][1];
                }
            }
        printf("%d %d %d\n",ans,ans1,m-ans1);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/arbitrary/p/2879001.html