zoukankan      html  css  js  c++  java
  • [hdu5313]二分图性质,dp

    题意:给定二分图,求添加的最多边数,使得添加之后还是二分图

     思路:如果原图可以分成X,Y两个点集,那么边数最多为|X||Y|条。由于|X|+|Y|==n,所以需要使|X|与|Y|尽量接近。先对原图进行染色,对每个连通块,求出它的两种颜色的点数差,并且交换染的颜色,染色方案依然成立。不妨设染色0和1,cnt[i]表示颜色为i的点的个数,并假设cnt[1]总是大于等于cnt[0],|X|对应cnt[1],|Y|对应cnt[0],

    (1)对于同一个连通块,由于可以改变第一次染的颜色,则有:

    cnt[1]-cnt[0] = ±abs(cnt[1]-cnt[0])                

    (2)对不同连通块,有:

    cnt[1]-cnt[0]=Σ±abs(cnt[1]-cnt[0])              

    左边表示最后的染色为1和0的点数差,也就是|X|-|Y|,右边是一个表达式,值取决于对每一个连通块取的正负情况。于是相当于在一系列正数前面添上正负号,使得最后结果是最小的正数,注意到每个数前面必须添上正号或符号,而所有正数的和是知道的,令为V,同时令第i个正数为Ai,于是转化为以V/2为背包容量、Ai为物品体积、求背包能放满的最大体积,用V减去2倍这个答案就是等号左边的最小值了。|X|-|Y|和|X|+|Y|都出来了,求出|X|、|Y|,|X||Y|-m便是答案。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    /* ******************************************************************************** */
    #include <iostream>                                                                 //
    #include <cstdio>                                                                   //
    #include <cmath>                                                                    //
    #include <cstdlib>                                                                  //
    #include <cstring>                                                                  //
    #include <vector>                                                                   //
    #include <ctime>                                                                    //
    #include <deque>                                                                    //
    #include <queue>                                                                    //
    #include <algorithm>                                                                //
    using namespace std;                                                                //
                                                                                        //
    #define pb push_back                                                                //
    #define mp make_pair                                                                //
    #define X first                                                                     //
    #define Y second                                                                    //
    #define all(a) (a).begin(), (a).end()                                               //
    #define foreach(i, a) for (typeof(a.begin()) it = a.begin(); it != a.end(); it ++)  //
                                                                                        //
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}    //
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>                    //
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;          //
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>      //
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>              //
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>   //
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}   //
                                                                                        //
    typedef pair<intint> pii;                                                         //
    typedef long long ll;                                                               //
    typedef unsigned long long ull;                                                     //
                                                                                        //
    /* -------------------------------------------------------------------------------- */
                                                                                        //
    template<typename T>bool umax(T &a, const T &b) {
        return a >= b? false : (a = b, true);
    }
     
    const int maxn = 1e4 + 7;
     
    struct Graph {
        vector<vector<int> > G;
        void clear() { G.clear(); }
        void resize(int n) { G.resize(n + 2); }
        void add(int u, int v) { G[u].push_back(v); }
        vector<int> & operator [] (int u) { return G[u]; }
    };
    Graph G;
     
    int color[maxn], cnt[3];
     
    void dfs(int node, int c) {
        color[node] = c;
        cnt[c] ++;
        for (int i = 0; i < G[node].size(); i ++) {
            int v = G[node][i];
            if (!color[v]) dfs(v, 3 - c);
        }
    }
    vector<int> dp;
    int a[maxn];
     
    int get(int n, int v) {
        sort(a + 1, a + 1 + n);
        dp.clear();
        dp.pb(0);
        int now = 0, ans = 0;
        bool have[12345] = {true};
        for (int i = 1; i <= n; i ++) {
            int sz = dp.size();
            for (int j = 0; j < sz; j ++) {
                int buf = dp[j] + a[i];
                if (buf <= v && !have[buf]) {
                    if (buf == v) return v;
                    dp.pb(buf);
                    have[buf] = true;
                    umax(ans, buf);
                }
            }
        }
        return ans;
    }
     
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt""r", stdin);
    #endif // ONLINE_JUDGE
        int T, n, m;
        cin >> T;
        while (T --) {
            cin >> n >> m;
            G.clear();
            G.resize(n);
            for (int i = 0; i < m; i ++) {
                int u, v;
                scanf("%d%d", &u, &v);
                G.add(u, v);
                G.add(v, u);
            }
            memset(color, 0, sizeof(color));
            int t = 0, total = 0;
            for (int i = 1; i <= n; i ++) {
                if (!color[i]) {
                    cnt[1] = cnt[2] = 0;
                    dfs(i, 1);
                    a[++ t] = cnt[1] - cnt[2];
                    if (a[t] < 0) a[t] = -a[t];
                    total += a[t];
                }
            }
            int y = total / 2, r = total - 2 * get(t, y);
            cout << (n + r) / 2 * (n - r) / 2 - m << endl;
        }
        return 0;                                                                       //
    }                                                                                   //
                                                                                        //
                                                                                        //
                                                                                        //
    /* ******************************************************************************** */
  • 相关阅读:
    小白学习React官方文档看不懂怎么办?1.起步
    部分安卓机调用相册跟相机出问题了
    var与let与const
    小白学习React官方文档看不懂怎么办?3.元素渲染
    小白学习React官方文档看不懂怎么办?2.JSX语法
    jQuery简单面试题
    HTML页面插入图片,使用background还是img标签
    HTML规范
    img标签不能直接作为body的子元素
    java 学习第三天小练习
  • 原文地址:https://www.cnblogs.com/jklongint/p/4681718.html
Copyright © 2011-2022 走看看