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 ...
随机推荐
- sql —— between
BETWEEN 操作符在 WHERE 子句中使用,作用是选取介于两个值之间的数据范围. 原表: 执行查询: 上面就可以搜索出得分为80~90的学生了,包含80,也包含90.
- 《mysql必知必会》笔记3(插入、更新、删除、创建删除更新表、视图)
十九:插入数据 1:insert语句用来将行插入数据表中,可以插入完整的行.行的一部分.插入多行.插入某些查询的结果. 2:不指定列名,可以这样插入: insert into customers va ...
- JavaScript 错误
try 语句测试代码块的错误. catch 语句处理错误. throw 语句创建自定义错误. JavaScript 错误 当 JavaScript 引擎执行 JavaScript 代码时,会发生各种错 ...
- 关于取List中的指定几条数据以及注意事项
list1 = list2.subList(start, end); start,end分别是第几个到第几个. 注意的是此方法和substring一样,包含前不包含结尾,取下标索引 另一个注意的地方是 ...
- python 数据的读取
- C++:只用初始化列表初始化变量的几种情况
1.类成员函数中const变量的初始化(也就是第一点) 有几个容易混淆的地方: (1)const 的变量只能通过构造函数的初始化列表进行初始化:(貌似在C++11中可以正常编译) (2)static ...
- et al.
et al. 英 [ˌet ˈæl] adv. <拉>以及其他人; [例句]Earlier research in conventional RCS modelling for d ...
- C# 设计模式 责任链
责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个 ...
- PyODPS DataFrame 的代码在哪里跑
在使用 PyODPS DataFrame 编写数据应用时,尽管编写的是同一个脚本文件,但其中的代码会在不同位置执行,这可能导致一些无法预期的问题,本文介绍当出现相关问题时,如何确定代码在何处执行,以及 ...
- 初识 Knative: 跨平台的 Serverless 编排框架
Knative 是什么 Knative 是 Google 在 2018 的 Google Cloud Next 大会上发布的一款基于 Kubernetes 的 Serverless 框架.Knativ ...