【UVA10859】Placing Lampposts

14 篇文章 0 订阅

题面

  As a part of the mission ‘Beautification of Dhaka City’, the government has decided to replace all the old lampposts with new expensive ones. Since the new ones are quite expensive and the budget is not up to the requirement, the government has decided to buy the minimum number of lampposts required to light the whole city.
  Dhaka city can be modeled as an undirected graph with no cycles, multi-edges or loops. There are several roads and junctions. A lamppost can only be placed on junctions. These lampposts can emit light in all the directions, and that means a lamppost that is placed in a junction will light all the roads leading away from it.
  The ‘Dhaka City Corporation’ has given you the road map of Dhaka city. You are hired to find the minimum number of lampposts that will be required to light the whole city. These lampposts can then be placed on the required junctions to provide the service. There could be many combinations of placing these lampposts that will cover all the roads. In that case, you have to place them in such a way that the number of roads receiving light from two lampposts is maximized.

题意

   Graph= { VE }, |V|=n |E|=m ,满足 mn
  在一个节点打上标记可以覆盖与该节点相邻的边,记覆盖所有边需要标记的点数为 x ,边两端点都被标记的条数记为A(记为双端点覆盖数),求出最小的 x ,如果x有相等的情况,求出最大的 A

解法

树型DP
  这个问题大家应该很熟悉……求树的最小点覆盖,本题只是在此基础上加了一小问,我们可以利用同样的方法解决
  求树的最小点覆盖的时候,我们设 fi0 i 节点的子树内部全部被覆盖,并且i号结点打了标记的最小标记数, fi1 i 节点子树内……并且i号结点没有打标记的最小标记数,那么有:

fk0=x=sonkminfx0fx1

fk1=x=sonkfx0

  与此同理,我们设 ci0 i 节点子树内部全部被覆盖,并且i号节点打了标记的双端点覆盖数, ci1 i 节点……并且i节点没有打标记……,那么有:
ck1=x=sonkcx0

ck0+=cx0+1fx0<fx1

ck0+=cx1fx0>fx1

ck0+=maxcx0+1cx1fx0=fx1

复杂度

O( Tn2

代码

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define Lint long long int
using namespace std;
const int MAXN=1010;
struct node
{
    int next,to;
}t[MAXN*2];
bool vis[MAXN];
int head[MAXN],num;
int f[MAXN][2],c[MAXN][2];
int T,n,m,ans;
int A1,A2;
void add(int u,int v)
{
    t[++num]=(node){ head[u],v };
    head[u]=num;
}
void dfs(int k,int fa)
{
    vis[k]=1;
    f[k][0]=1,f[k][1]=0;
    c[k][0]=0,c[k][1]=0;
    for(int i=head[k],x; i ;i=t[i].next)
    {
        x=t[i].to;
        if( x==fa)   continue ;
        dfs( x,k );
        if( f[x][0]<f[x][1] )   f[k][0]+=f[x][0],c[k][0]+=c[x][0]+1;
        else
        {
            f[k][0]+=f[x][1];
            if( f[x][0]>f[x][1] )   c[k][0]+=c[x][1];
            else   c[k][0]+=max( c[x][1],c[x][0]+1 );
        }
        f[k][1]+=f[x][0],c[k][1]+=c[x][0];
    }
}
int main()
{
    int u,v;
    scanf("%d",&T);
    while( T-- )
    {
        A1=A2=ans=num=0;
        memset( c,0x0,sizeof c );
        memset( f,0x0,sizeof f );
        memset( vis,0x0,sizeof vis );
        memset( head,0x0,sizeof head );
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            u++,v++;
            add( u,v ),add( v,u );
        }
        for(int i=1;i<=n;i++)
            if( !vis[i] )
            {
                dfs( i,0 );
                ans+=min( f[i][0],f[i][1] );
                if( f[i][0]<f[i][1] )   A1+=c[i][0];
                else
                    if( f[i][0]>f[i][1] )   A1+=c[i][1];
                    else   A1+=max( c[i][0],c[i][1] );
            }
        A2=m-A1;
        printf("%d %d %d\n",ans,A1,A2);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值