zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    买卖股票的最佳时机
    删除排序数组中的重复数字
    软件工程第五次作业:个人总结
    软件工程第二次作业——结对编程
    第一次软件工程作业补充plus
    第二次(四则运算,)
    我的第一次
    软件工程--个人总结
    软件工程第二次作业—结对编程
    软件工程第一次作业补充
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2879001.html
Copyright © 2011-2022 走看看