Light oj 1230 - Placing Lampposts(树形dp)

1230 - Placing Lampposts
Time Limit: 2 second(s)Memory Limit: 32 MB

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 still cover all the roads. In that case, you have to place them in such a way so that the number of roads receiving light from two lampposts is maximized. (A careful thought will reveal that all the roads will get light either from one post or two posts).

Input

Input starts with an integer T (≤ 30), denoting the number of test cases.

Each case starts with a blank line. The next line contains two integers N (1 ≤ N ≤ 1000) and M (0 ≤ M < N) which indicate the number of junctions and roads respectively. The junctions are numbered from 0 to N-1. Each of the next M lines contains two integers a and b (0 ≤ a, b < N, a ≠ b), which denotes that there is a road from junction a to b.

Output

For each case, print the case number, the minimum number of lampposts required to light the whole city, the number of roads that are receiving lights from two lampposts and the number of roads that are receiving light from only one lamppost.

Sample Input

Output for Sample Input

2

 

4 3

0 1

1 2

2 3

 

5 4

0 1

0 2

0 3

0 4

Case 1: 2 1 2

Case 2: 1 0 4

 


PROBLEM SETTER: SOHEL HAFIZ


#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>

#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)

#define bug printf("hihi\n")

#define eps 1e-12

typedef long long ll;
using namespace std;

#define N 1005

int dp[N][2];
int f[N][2];
int father[N],n,m;

int head[N],num;

struct stud{
   int to,ne;
}e[N*2];

int cha(int x)
{
    if(x!=father[x])
        father[x]=cha(father[x]);
    return father[x];
}

inline void add(int u,int v)
{
   e[num].to=v;
   e[num].ne=head[u];
   head[u]=num++;
}

void dfs(int u,int pre)
{
    dp[u][0]=0;
    dp[u][1]=1;
    f[u][0]=f[u][1]=0;
    for(int i=head[u];i!=-1;i=e[i].ne)
    {
        int to=e[i].to;
        if(to==pre) continue;
        dfs(to,u);
        dp[u][0]+=dp[to][1];
        f[u][0]+=f[to][1];

        if(dp[to][1]<dp[to][0])
        {
            dp[u][1]+=dp[to][1];
            f[u][1]+=f[to][1]+1;
        }
        else
            if(dp[to][1]>dp[to][0])
        {
              dp[u][1]+=dp[to][0];
              f[u][1]+=f[to][0];
        }
        else
        {
            dp[u][1]+=dp[to][0];
            f[u][1]+=max(f[to][0],f[to][1]+1);
        }
    }
}

int main()
{
    int i,j,ca=0,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));
        num=0;
        for(int i=0;i<=n;i++)
            father[i]=i;
        int u,v;
        i=m;
        while(i--)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
            father[cha(u)]=cha(v);
        }
        int all,ans;
        all=ans=0;
        for(int i=0;i<n;i++)
            if(father[i]==i)
            {
                dfs(i,-1);
                if(dp[i][0]<dp[i][1])
                {
                    all+=dp[i][0];
                    ans+=f[i][0];
                }
                else
                    if(dp[i][0]>dp[i][1])
                {
                    all+=dp[i][1];
                    ans+=f[i][1];
                }
                else
                {
                    all+=dp[i][0];
                    ans+=max(f[i][0],f[i][1]);
                }
            }
         printf("Case %d: %d %d %d\n",++ca,all,ans,m-ans);
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值