【UVA10859】Placing Lampposts

題面

  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
  這個問題大家應該很熟悉……求樹的最小點覆蓋,本題只是在此基礎上加了一小問,我們可以利用同樣的方法解決
  求樹的最小點覆蓋的時候,我們設fi0i 節點的子樹內部全部被覆蓋,並且i 號結點打了標記的最小標記數,fi1i 節點子樹內……並且i 號結點沒有打標記的最小標記數,那麼有:

fk0=x=sonkminfx0fx1

fk1=x=sonkfx0

  與此同理,我們設ci0i 節點子樹內部全部被覆蓋,並且i 號節點打了標記的雙端點覆蓋數,ci1i 節點……並且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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章