2019 ICPC 陕西西安邀请赛 D. Miku and Generals
传送门:https://nanti.jisuanke.com/t/39271
题意:
给你n个人,每个人有一个权值 a_i ,(a_i是可以被100整除的))现在需要你将n个人分成两组,有m个关系,a和b有关系代表a和b不能放在同一个组内,为了两组实力尽量平均,要你求两组权值差值最小时最大的值是哪一个
题解:
二分图染色+dp
首先我们知道n个人必须全选分为两组,其次题目保证有解
因此我们很容易想到如果a->b,b->c,那么a一定和c要分在同一组内
这样我们就得到了很多个联通块
错误想法:我们得到了num个联通块后直接将num个联通块做01背包就可以求出差值最小时最大值,dp状态定义为前i个物品,容量为j时的最大值,但是实际上这样有可能把错误的情况考虑进来,例如两个矛盾的块同时放进一个背包,例如这组数据
2
4 1
300 300 100 500
1 2
6 4
1000 2000 1000 1500 1000 1500
1 2
2 3
4 5
5 6
01背包得到的答案是600 和 4000,实际上应该是 800和5000
正确想法,我们将物品分成联通块后,对分成的两个联通块做差值,之后枚举差值能否达到才是最优解,为了防止差值为负,我们在中间加上一个比较大的数即可
代码:
错误写法:
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef long long ll;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
struct EDGE {
int v, nxt;
} edge[maxn << 1];
int head[maxn], tot;
void add_edge(int u, int v) {
edge[tot].v = v;
edge[tot].nxt = head[u];
head[u] = tot++;
}
int a[maxn];
int num[maxn];
int num1, num2;
int vis[maxn];
int dp[205][maxn];
void dfs(int u, int flag) {
vis[u] = 1;
if(flag) num1 += a[u];
else num2 += a[u];
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(vis[v]) continue;
dfs(v, !flag);
}
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--) {
int n, m;
memset(head, -1, sizeof(head));
tot = 0;
int cur = 0;
int sum = 0, ret;
memset(vis, 0, sizeof(vis));
memset(num, 0, sizeof(num));
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i] /= 100;
sum += a[i];
}
ret = sum / 2;
for(int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
for(int i = 1; i <= n; i++) {
if(!vis[i]) {
num1 = 0, num2 = 0;
dfs(i, 0);
if(num1 != 0) {
num[++cur] = num1;
}
if(num2 != 0) {
num[++cur] = num2;
}
}
}
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= cur; i++) {
for(int j = 0; j <= ret; j++) {
dp[i][j] = dp[i - 1][j];
if(j >= num[i])dp[i][j] = max(dp[i][j], dp[i - 1][j - num[i]] + num[i]);
}
}
printf("%d\n", (sum - dp[cur][ret]) * 100);
}
return 0;
}
正确写法:
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef long long ll;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
struct EDGE {
int v, nxt;
} edge[maxn << 1];
int head[maxn], tot;
void add_edge(int u, int v) {
edge[tot].v = v;
edge[tot].nxt = head[u];
head[u] = tot++;
}
int a[maxn];
int num[maxn];
int num1, num2;
int vis[maxn];
int dp[205][maxn];
void dfs(int u, int flag) {
vis[u] = 1;
if(flag) num1 += a[u];
else num2 += a[u];
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(vis[v]) continue;
dfs(v, !flag);
}
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--) {
int n, m;
memset(head, -1, sizeof(head));
tot = 0;
int cur = 0;
int sum = 0, ret;
memset(vis, 0, sizeof(vis));
memset(num, 0, sizeof(num));
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i] /= 100;
sum += a[i];
}
for(int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
ret = 0;
for(int i = 1; i <= n; i++) {
if(!vis[i]) {
num1 = 0, num2 = 0;
dfs(i, 0);
num[++cur] += abs (num1 - num2);
ret += abs(num1 - num2);
}
}
memset(dp, 0, sizeof(dp));
dp[0][100000] = 1;
for (int i = 1; i <= cur; i++) {
for (int j = -ret; j <= ret; j++) {
if (dp[i - 1][j - num[i] + 100000]) dp[i][j + 100000] = 1;
if (dp[i - 1][j + num[i] + 100000]) dp[i][j + 100000] = 1;
}
}
for (int i = 100000; i <= 100000 + ret; i++) {
if (dp[cur][i]) {
int x = i - 100000;
printf("%d\n", 100 * ((sum - x) / 2 + x));
break;
}
}
}
return 0;
}
2019 ICPC 陕西西安邀请赛 D. Miku and Generals的更多相关文章
- ACM-ICPC 2019 西安邀请赛 D.Miku and Generals(二分图+可行性背包)
“Miku is matchless in the world!” As everyone knows, Nakano Miku is interested in Japanese generals, ...
- 2019 ACM/ICPC Asia Regional shanxia D Miku and Generals (二分图黑白染色+01背包)
Miku is matchless in the world!” As everyone knows, Nakano Miku is interested in Japanese generals, ...
- 2019 icpc南昌全国邀请赛-网络选拔赛J题 树链剖分+离线询问
链接:https://nanti.jisuanke.com/t/38229 题意: 给一棵树,多次查询,每次查询两点之间权值<=k的边个数 题解: 离线询问,树链剖分后bit维护有贡献的位置即可 ...
- 计蒜客 39272.Tree-树链剖分(点权)+带修改区间异或和 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest E.) 2019ICPC西安邀请赛现场赛重现赛
Tree Ming and Hong are playing a simple game called nim game. They have nn piles of stones numbered ...
- ACM-ICPC 2018全国邀请赛(陕西西安)
一.火车晚点 星期五下午4.36的火车,我们3点到了长沙火车站.差不多4点了,提示,晚点1h45min,DZC马上说,不知道会不会延误郑州到西安的那趟车.过了一会,又提示,晚点2h17min,再过一会 ...
- 2014嘉杰信息杯ACM/ICPC湖南程序设计邀请赛暨第六届湘潭市程序设计竞赛
比赛链接: http://202.197.224.59/OnlineJudge2/index.php/Contest/problems/contest_id/36 题目来源: 2014嘉杰信息杯ACM ...
- 2019 ICPC 南昌网络赛
2019 ICPC 南昌网络赛 比赛时间:2019.9.8 比赛链接:The 2019 Asia Nanchang First Round Online Programming Contest 总结 ...
- 2019 ICPC Asia Nanjing Regional
2019 ICPC Asia Nanjing Regional A - Hard Problem 计蒜客 - 42395 若 n = 10,可以先取:6,7,8,9,10.然后随便从1,2,3,4,5 ...
- 西安区域赛 D.Miku and Generals 二分图+背包
Miku and Generals Describe "Miku is matchless in the world!" As everyone knows, Nakano Mik ...
随机推荐
- Inno Setup生成桌面快捷方式
在做项目的时候,需要打包成exe安装包.先前使用的是vs来打包,生成了setup.exe 和 *.msi的安装文件,不过也算顺利. 后因为要求采取 Inno Setup来打包程序,其中遇到个创建快捷方 ...
- 开启远程XUL
参考:https://developer.mozilla.org/zh-cn/Remote_XUL firefox自4.0起(2011年4月版本,目前最新版为13.0),开始禁用远程XUL,这阻碍了初 ...
- jenkins使用教程!
http://jenkins-ci.org/ 首先去官方下载war包,直接安装jenkins的方式比较麻烦. 下载tomcat,jdk和ant cd /optwget http://mirrors.h ...
- postman认证使用篇(五)
postman 认证使用篇(五) Authorization 尽管请求编辑器已经足够强大去构造各种各样的请求,但是有的时候你的请求可能是需要认证,那么就可以尝试使用下面的认证功能了(由于认证的参数信息 ...
- python 使用异常代替返回状态码
- Kubernetes1.4新特性前瞻:设置JOB执行计划
(一) 核心概念 Kubernetes在新版中会新增了一个设置JOB执行计划的功能,在1.3中已经可以初见端倪了,从进度上来看会在1.4版本中进行发布,下面我们先睹为快. Kubernetes通过这 ...
- 2016 Asia Jakarta Regional Contest J - Super Sum UVALive - 7720 【快速幂+逆元】
J-Super Sum 题目大意就是给定N个三元组<a,b,c>求Σ(a1^k1*a2^k2*...*ai^ki*..an^kn)(bi<=ki<=ci) 唉.其实题目本身不难 ...
- 一维数组的求平均成绩 Day06
package com.sxt.arraytest1; /* * 求班里学生的平均成绩,以及成绩的综合 输出每个同学的成绩 */ import java.util.Arrays; import jav ...
- Java成员方法,构造方法
//作者:qingfeng//2017/2/17//功能:理解类的成员方法和构造方法class CreatWays{ public static void main(String args[]){ ...
- 基本的Sql编写注意事项
基本的Sql编写注意事项 尽量少用IN操作符,基本上所有的IN操作符都可以用EXISTS代替. 不用NOT IN操作符,可以用NOT EXISTS或者外连接+替代. Oracle在执行IN子查询时,首 ...