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

思路:如果原图可以分成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;                                                                       //
}                                                                                   //
                                                                                    //
                                                                                    //
                                                                                    //
/* ******************************************************************************** */

[hdu5313]二分图性质,dp的更多相关文章

  1. 【POJ 1112】Team Them Up!(二分图染色+DP)

    Description Your task is to divide a number of persons into two teams, in such a way, that: everyone ...

  2. Rigid Frameworks (画图二分图规律 + DP + 数学组合容斥)

    题意:方格n*m,然后对于每一个格子有3种画法1左对角线2右对角线3不画,求让图形稳定的画法有多少种? 思路:通过手画二分图可以发现当二分图联通时改图满足条件,然后我们对于一个dp[n][m]可以利用 ...

  3. Codeforces 1461F - Mathematical Expression(分类讨论+找性质+dp)

    现场 1 小时 44 分钟过掉此题,祭之 大力分类讨论. 如果 \(|s|=1\),那么显然所有位置都只能填上这个字符,因为你只能这么填. scanf("%d",&n);m ...

  4. CF 407B Long Path[观察性质 DP]

    B. Long Path time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  5. 【gdoi2018 day2】第二题 滑稽子图(subgraph)(性质DP+多项式)

    题目大意 [gdoi2018 day2]第二题 滑稽子图(subgraph) 给你一颗树\(T\),以及一个常数\(K\),对于\(T\)的点集\(V\)的子集\(S\). 定义\(f(S)\)为点集 ...

  6. 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)

    [GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...

  7. poj-1112 (二分图染色+dp分组)

    #include <iostream> #include <algorithm> #include <cstring> using namespace std; ; ...

  8. bzoj 5006(洛谷 4547) [THUWC2017]Bipartite 随机二分图——期望DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5006 https://www.luogu.org/problemnew/show/P4547 ...

  9. [agc001E]BBQ Hard[组合数性质+dp]

    Description 传送门 Solution 题目简化后要求的实际上是$\sum _{i=1}^{n-1}\sum _{j=i+1}^{n}C^{A[i]+A[j]}_{A[i]+A[j]+B[i ...

随机推荐

  1. PHP函数:array_key_exists

    array_key_exists()  - 检查数组里是否有指定的键名或索引. 注意:array_key_exists() 仅仅搜索第一维的键. 多维数组里嵌套的键不会被搜索到. 说明: rray_k ...

  2. Linux 平台 安装 Composer

    1.检查是否安装 composer --version 2.下载安装 php -r "copy('https://install.phpcomposer.com/installer', 'c ...

  3. 1. git 本地给远程仓库创建分支 三步法

    命令如下: 1:本地创建分支dev 1 2 Peg@PEG-PC /D/home/myself/Symfony (master) $ git branch dev 2:下面是把本地分支提交到远程仓库 ...

  4. 如何防止CDN防护被绕过

    当攻击者发现目标站点存在CDN防护的时候,会尝试通过查找站点的真实IP,从而绕过CDN防护.我们来看一个比较常见的基于公有云的高可用架构,如下:CDN(入口层)->WAF(应用层防护)-> ...

  5. python3-邮件发送-不同格式

    0x00 邮件格式 要发邮件,总要先了解邮件格式吧,这里指的是邮件的各个部分与python中SMTP所对应的一些必须的格式 0x01 简单发送邮件格式如下: import smtplib from e ...

  6. vue路由中 Navigating to current location ("/router") is not allowed

    报错原因:多次点击同一路由,导致路由被多次添加 解决方法: router/index中添加以下代码: //router/index.js Vue.use(VueRouter) //导入vue路由 co ...

  7. PHP中静态(static)调用非静态方法详解--调用!!!

    来源:https://www.cnblogs.com/yolo-bean/p/7739265.html 这里分析了php面向对象中static静态属性和静态方法的调用.关于它们的调用(能不能调用,怎么 ...

  8. 关于VUE的路由地址问题

    目前我们VUE的项目都是单页面应用,路由地址全都是#以不同的锚点去分发,根目录就是 http://localhost:8080/index#/   (至于为什么不是http://localhost:8 ...

  9. 2019-2020-1 20199308《Linux内核原理与分析》第四周作业

    <Linux内核分析> 第三章 MenuOS的构造 3.1 Linux内核源代码简介 操作系统的"两把宝剑" 中断上下文:保存现场和恢复现场 进程上下文 目录结构 ar ...

  10. Java第一阶段作业总结

    目录 0.前言 1.作业过程总结 2.OO设计心得 3.测试的理解与实践 4.课程收获 5.对课程的建议 前言 本次博客针对第一阶段的三次作业发表总结,作业要求主要是初学者对于Java的基本语法.用法 ...