IT Restaurants CodeForces - 212E(樹形dp)

Сity N. has a huge problem with roads, food and IT-infrastructure. In total the city has n junctions, some pairs of them are connected by bidirectional roads. The road network consists of n - 1 roads, you can get from any junction to any other one by these roads. Yes, you’re right — the road network forms an undirected tree.

Recently, the Mayor came up with a way that eliminates the problems with the food and the IT-infrastructure at the same time! He decided to put at the city junctions restaurants of two well-known cafe networks for IT professionals: “iMac D0naldz” and “Burger Bing”. Since the network owners are not friends, it is strictly prohibited to place two restaurants of different networks on neighboring junctions. There are other requirements. Here’s the full list:

each junction must have at most one restaurant;
each restaurant belongs either to “iMac D0naldz”, or to “Burger Bing”;
each network should build at least one restaurant;
there is no pair of junctions that are connected by a road and contains restaurants of different networks.
The Mayor is going to take a large tax from each restaurant, so he is interested in making the total number of the restaurants as large as possible.

Help the Mayor to analyze the situation. Find all such pairs of (a, b) that a restaurants can belong to “iMac D0naldz”, b restaurants can belong to “Burger Bing”, and the sum of a + b is as large as possible.

Input
The first input line contains integer n (3 ≤ n ≤ 5000) — the number of junctions in the city. Next n - 1 lines list all roads one per line. Each road is given as a pair of integers x i, y i (1 ≤ x i, y i ≤ n) — the indexes of connected junctions. Consider the junctions indexed from 1 to n.

It is guaranteed that the given road network is represented by an undirected tree with n vertexes.

Output
Print on the first line integer z — the number of sought pairs. Then print all sought pairs (a, b) in the order of increasing of the first component a.

Examples
Input
5
1 2
2 3
3 4
4 5
Output
3
1 3
2 2
3 1
Input
10
1 2
2 3
3 4
5 6
6 7
7 4
8 9
9 10
10 4
Output
6
1 8
2 7
3 6
6 3
7 2
8 1
Note
The figure below shows the answers to the first test case. The junctions with “iMac D0naldz” restaurants are marked red and “Burger Bing” restaurants are marked blue.

題意:
每個點可以染黑色或者白色或者不染色,相鄰點顏色不能相同。(a,b)表示a個點染白色,b個點染黑色。求a+b最大的所有(a,b)

思路:
一個可行的方案是選葉子節點染黑色,父節點不染色,其他點染白色。則a+b爲n-1。
故最優方案就是n-1,染色的方法是選一個點不染色,然後子樹內全部染相同顏色。

數據範圍很小(5000),則可以對每個點分別枚舉一遍,然後對每個點的子樹大小作爲物品重量,n作爲揹包容量,跑n次揹包。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
typedef long long ll;
const int maxn = 5e3 + 7;

int dp[maxn],siz[maxn],res[maxn];
int head[maxn],nex[maxn * 2],to[maxn * 2],tot;
int n;

void add(int x,int y) {
    to[++tot] = y;
    nex[tot] = head[x];
    head[x] = tot;
}

void dfs(int u,int fa) {
    siz[u] = 1;
    for(int i = head[u];i;i = nex[i]) {
        int v = to[i];
        if(v == fa) continue;
        dfs(v,u);
        siz[u] += siz[v];
    }
}

void solve() {
    int cnt = 0;
    for(int i = 1;i <= n;i++) {
        memset(dp,0,sizeof(dp));
        memset(siz,0,sizeof(siz));
        dp[0] = 1;
        dfs(i,-1);
        
        for(int j = head[i];j;j = nex[j]) {
            int num = siz[to[j]];
            for(int k = n;k >= 1;k--) {
                if(k >= num && dp[k - num]) {
                    dp[k] = res[k] = 1;
                }
            }
        }
    }
    
    for(int i = 1;i < n - 1;i++) {
        if(res[i]) {
            cnt++;
        }
    }
    
    printf("%d\n",cnt);
    for(int i = 1;i < n - 1;i++) {
        if(res[i]) {
            printf("%d %d\n",i,n - 1 - i);
        }
    }
}

int main() {
    scanf("%d",&n);
    for(int i = 1;i < n;i++) {
        int x,y;scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    solve();
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章