zoukankan      html  css  js  c++  java
  • Codeforces Round #322 (Div. 2) —— F. Zublicanes and Mumocrates

    It's election time in Berland. The favorites are of course parties of zublicanes and mumocrates. The election campaigns of both parties include numerous demonstrations on n main squares of the capital of Berland. Each of the n squares certainly can have demonstrations of only one party, otherwise it could lead to riots. On the other hand, both parties have applied to host a huge number of demonstrations, so that on all squares demonstrations must be held. Now the capital management will distribute the area between the two parties.

    Some pairs of squares are connected by (n - 1) bidirectional roads such that between any pair of squares there is a unique way to get from one square to another. Some squares are on the outskirts of the capital meaning that they are connected by a road with only one other square, such squares are called dead end squares.

    The mayor of the capital instructed to distribute all the squares between the parties so that the dead end squares had the same number of demonstrations of the first and the second party. It is guaranteed that the number of dead end squares of the city is even.

    To prevent possible conflicts between the zublicanes and the mumocrates it was decided to minimize the number of roads connecting the squares with the distinct parties. You, as a developer of the department of distributing squares, should determine this smallest number.

    Input

    The first line of the input contains a single integer n (2 ≤ n ≤ 5000) — the number of squares in the capital of Berland.

    Next n - 1 lines contain the pairs of integers x, y (1 ≤ x, y ≤ n, x ≠ y) — the numbers of the squares connected by the road. All squares are numbered with integers from 1 to n. It is guaranteed that the number of dead end squares of the city is even.

    Output

    Print a single number — the minimum number of roads connecting the squares with demonstrations of different parties.

    Sample test(s)
    input
    8
    1 4
    2 4
    3 4
    6 5
    7 5
    8 5
    4 5
    output
    1
    input
    5
    1 2
    1 3
    1 4
    1 5
    output
    2

    题目大意:

    一棵树,5000个结点,两个政党,你必须满证这两个政党占领的度数为1的点的数量相同,其他点随意,然后求的是最少的X。这个X指的是连接两个不同政党的边的数量.

    注意,所以点必须被某个政党占领,同时题目保证度数为1的政党数目相同.

    解题报告:

    不妨有dp(i,j,k) , k ∈ {0,1} 表示将以 i 为根的子树全部染色,同时i染K色,同时下面有J个染0色的度一点.

    转移比较简单,这里不再累述.

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <stack>
    #include <map>
    #include <set>
    #include <queue>
    #include <iomanip>
    #include <string>
    #include <ctime>
    #include <list>
    #include <bitset>
    #include <conio.h>
    typedef unsigned char byte;
    #define pb push_back
    #define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
    #define local freopen("in.txt","r",stdin)
    #define pi acos(-1)
    
    using namespace std;
    const int maxn = 5e3 + 15;
    struct Edge{int v , nxt;};
    int sz[maxn],head[maxn],n,tot=0,root,dp[maxn][maxn][2],errorcode;
    Edge e[maxn*2];
    
    void add(int u,int v)
    {
        e[tot].v = v , e[tot].nxt= head[u],head[u] = tot++ , sz[u]++;
    }
    
    void initiation()
    {
        memset(sz,0,sizeof(sz));memset(dp,0x3f,sizeof(dp));memset(head,-1,sizeof(head)); 
        errorcode = dp[0][0][0];
        scanf("%d",&n);
        for(int i = 1 ; i < n ; ++ i)
        {
            int u , v;
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
    }
    
    inline void updata(int & x ,int v)
    {
        x = min(x , v );
    }
    
    int dfs(int u ,int fa)
    {
        int res = 0;
        if(sz[u] == 1)  res = 1 ,  dp[u][1][0] = dp[u][0][1] = 0;
        else dp[u][0][1] = dp[u][0][0] = 0;
        for(int i = head[u] ; ~i ; i = e[i].nxt)
        {
            int v = e[i].v;
            if(v == fa) continue;
            int t = dfs(v,u);
            for(int j = res ; j >= 0 ; -- j)
            {
                for(int k = t ; k >= 1 ; -- k)
                {
                    updata( dp[u][j+k][0] , dp[u][j][0] + dp[v][k][1] + 1);
                    updata( dp[u][j+k][0] , dp[u][j][0] + dp[v][k][0]);
                     updata( dp[u][j+k][1] , dp[u][j][1] + dp[v][k][1]);
                    updata( dp[u][j+k][1] , dp[u][j][1] + dp[v][k][0] + 1);
                }
                int s1 = min(dp[v][0][1] + 1 , dp[v][0][0]);
                dp[u][j][0] = s1 > (1<<20) ? errorcode : s1 + dp[u][j][0];
                s1 = min(dp[v][0][1],dp[v][0][0]+1); 
                dp[u][j][1] = s1 > (1<<20) ? errorcode : s1 + dp[u][j][1];
            }
            res += t;
        }
        return res;
    }
    
    void solve()
    {
        int res = 0;
        for(int i = 1 ; i <= n ; ++ i) if(sz[i] != 1) {root = i ; break;}
        for(int i = 1 ; i <= n ; ++ i) if(sz[i] == 1) res ++ ;
        dfs(root,0);
        printf("%d
    ",min(dp[root][res/2][0],dp[root][res/2][1]));
    }
    
    int main(int argc,char *argv[])
    {
        initiation();
        if(n == 2) printf("1
    ");
        else solve();
        return 0;
    }
  • 相关阅读:
    细细审视的你代码:异步消息处理
    [C++] 加速make的编译
    分析一下12306网站
    [Linux] 通过shell给unix socket发送数据
    shell中如何设置自增的变量
    多系统的 启动 顺序 修改
    对apk包进行odex优化的目的
    Android之所以不需要关闭后台运行程序 的 理由
    shell中如何设置自增的变量
    eclipse 小结
  • 原文地址:https://www.cnblogs.com/Xiper/p/4847708.html
Copyright © 2011-2022 走看看