Magic Potion(网络流)
2018南京的铜牌题,听说学长他们上来就A了,我这个图论选手也就上手做了做,结果一言难尽......
发此篇博客希望自己能牢记自己的菜...
本题大意:有n个heros和m个monsters大战,每个heros只能杀一个monsters且他们只能杀固定编号的monsters,现在有药水k瓶,如果英雄喝了药水那么它又可以多杀一个怪兽,每个英雄最多能喝一瓶药水。现在给你n, m, k,还有n个英雄各自能击杀怪兽的编号,问这些英雄最多能杀多少怪兽。
题解太水,大佬请绕道。。。
这里我们将英雄初始情况下能杀一个人定义为英雄的初始能量。
我用的网络流,别的都是正常思路,唯一一点就是,药水这个点,我们可以考虑从超级源点起向另一个源点引一条容量为k的边,从这个源点向英雄连一条容量为1的边表示药水。
千万不要像傻逼的我。。。
下面介绍一下我的做法。。。超级源点给附加源点提供药水,然后附加源点给英雄,英雄有一个初始能量?哦好了那我们把英雄拆点成a1, a2,给他a2一个能量就可以了,然后让a2代替英雄做该做的事,具体做法是附加源点给a1药水,a1自己本来有一个能量然后还可以接收药水(起始流量为1,容量为2),a2去打怪兽,然后向超级汇点统计。。。。。。
总的来说我的做法就可以描述为,正解的初始能量是超级源点给的,这本来也是常规思路,我个杠精非得拆点让他兄弟给,至今不明白为什么错了,堪忧。
哦对了,样例都没过一直感觉自己毫无问题,输出中间状态发现药水给出去了但是英雄连自己的初始能量都没用掉。。。
恨自己为什么不常规思路。。。奇葩
下面是正解代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + , maxm = maxn * maxn * , inf = 0x3f3f3f3f; struct Edge {
int to, cap, flow, next, from;
} edge[maxm << ]; int tot, head[maxn << ], que[maxn << ], dep[maxn << ], cur[maxn << ], sta[maxn << ]; void init() {
tot = ;
memset(head, -, sizeof head);
} void addedge(int u, int v, int cap) {
edge[tot].to = v; edge[tot].cap = cap; edge[tot].flow = ; edge[tot].from = u;
edge[tot].next = head[u]; head[u] = tot ++;
edge[tot].to = u; edge[tot].cap = ; edge[tot].flow = ; edge[tot].from = v;
edge[tot].next = head[v]; head[v] = tot ++;
} bool bfs(int s, int t, int n) {
memset(dep, -, sizeof dep[] * (n + ));
int front = , tail = ;
dep[s] = ;
que[tail ++] = s;
while(front < tail) {
int u = que[front ++];
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(edge[i].cap > edge[i].flow && dep[v] == -) {
dep[v] = dep[u] + ;
if(v == t) return true;
que[tail ++] = v;
}
}
}
return false;
} int dinic(int s, int t, int n) {
int maxflow = ;
while(bfs(s, t, n)) {
for(int i = ; i <= n; i ++) cur[i] = head[i];
int u = s, tail = ;
while(~cur[s]) {
if(u == t) {
int tp = inf;
for(int i = tail - ; i >= ; i --)
tp = min(tp, edge[sta[i]].cap - edge[sta[i]].flow);
maxflow += tp;
for(int i = tail - ; i >= ; i --) {
edge[sta[i]].flow += tp;
edge[sta[i] ^ ].flow -= tp;
if(edge[sta[i]].cap - edge[sta[i]].flow == ) tail = i;
}
u = edge[sta[tail] ^ ].to;
} else if(~ cur[u] && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + == dep[edge[cur[u]].to]) {
sta[tail ++] = cur[u];
u = edge[cur[u]].to;
} else {
while(u != s && cur[u] == -)
u = edge[sta[-- tail] ^ ].to;
cur[u] = edge[cur[u]].next;
}
}
}
return maxflow;
} int main() {
int s1, s2, t;
int n, m, k;
int num, v;
init();
scanf("%d %d %d", &n, &m, &k);
s1 = n + m + , s2 = s1 + , t = s2 + ;
addedge(s1, s2, k);
for(int u = ; u <= n; u ++) {
addedge(s2, u, );
addedge(s1, u, );
scanf("%d", &num);
while(num --) {
scanf("%d", &v);
addedge(u, n + v, );
}
}
for(int i = ; i <= m; i ++) {
addedge(n + i, t, );
}
printf("%d\n", dinic(s1, t, n + m + ));
return ;
}
下面是样例都没过的代码???
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + , maxm = maxn * maxn * , inf = 0x3f3f3f3f; struct Edge {
int to, cap, flow, next, from;
} edge[maxm << ]; int tot, head[maxn << ], que[maxn << ], dep[maxn << ], cur[maxn << ], sta[maxn << ]; void init() {
tot = ;
memset(head, -, sizeof head);
} void addedge(int u, int v, int flow, int cap) {
edge[tot].to = v; edge[tot].cap = cap; edge[tot].flow = flow; edge[tot].from = u;
edge[tot].next = head[u]; head[u] = tot ++;
edge[tot].to = u; edge[tot].cap = ; edge[tot].flow = ; edge[tot].from = v;
edge[tot].next = head[v]; head[v] = tot ++;
} bool bfs(int s, int t, int n) {
memset(dep, -, sizeof dep[] * (n + ));
int front = , tail = ;
dep[s] = ;
que[tail ++] = s;
while(front < tail) {
int u = que[front ++];
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(edge[i].cap > edge[i].flow && dep[v] == -) {
dep[v] = dep[u] + ;
if(v == t) return true;
que[tail ++] = v;
}
}
}
return false;
} int dinic(int s, int t, int n) {
int maxflow = ;
while(bfs(s, t, n)) {
for(int i = ; i <= n; i ++) cur[i] = head[i];
int u = s, tail = ;
while(~cur[s]) {
if(u == t) {
int tp = inf;
for(int i = tail - ; i >= ; i --)
tp = min(tp, edge[sta[i]].cap - edge[sta[i]].flow);
maxflow += tp;
for(int i = tail - ; i >= ; i --) {
edge[sta[i]].flow += tp;
edge[sta[i] ^ ].flow -= tp;
if(edge[sta[i]].cap - edge[sta[i]].flow == ) tail = i;
}
u = edge[sta[tail] ^ ].to;
} else if(~ cur[u] && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + == dep[edge[cur[u]].to]) {
sta[tail ++] = cur[u];
u = edge[cur[u]].to;
} else {
while(u != s && cur[u] == -)
u = edge[sta[-- tail] ^ ].to;
cur[u] = edge[cur[u]].next;
}
}
}
return maxflow;
} int main() {
int s1, s2, t;
int n, m, k;
int num, v;
init();
scanf("%d %d %d", &n, &m, &k);
s1 = * n + m + , s2 = s1 + , t = s2 + ;
addedge(s1, s2, , k);
for(int u = ; u <= n; u ++) {
addedge(s2, u, , );//
addedge(u, u + n, , );
scanf("%d", &num);
while(num --) {
scanf("%d", &v);
addedge(u + n, * n + v, , );//
}
}
for(int i = ; i <= m; i ++) {
addedge( * n + i, t, , );//
}
printf("%d\n", dinic(s1, t, * n + m + ));
for(int i = ; i <= tot; i ++) {
if(edge[i].flow > && !(i & )) {
printf("%d %d %d\n", edge[i].from, edge[i].to, edge[i].flow);
}
}
return ;
}
甚至现在还认为自己是对的...
Magic Potion(网络流)的更多相关文章
- 2018ACM-ICPC亚洲区域赛南京站I题Magic Potion(网络流)
http://codeforces.com/gym/101981/attachments 题意:有n个英雄,m个敌人,k瓶药剂,给出每个英雄可以消灭的敌人的编号.每个英雄只能消灭一个敌人,但每个英雄只 ...
- Magic Potion(最大流,跑两遍网络流或者加一个中转点)
Magic Potion http://codeforces.com/gym/101981/attachments/download/7891/20182019-acmicpc-asia-nanjin ...
- hdu4149 Magic Potion
Magic Potion Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tota ...
- Gym 101981I - Magic Potion - [最大流][2018-2019 ACM-ICPC Asia Nanjing Regional Contest Problem I]
题目链接:http://codeforces.com/gym/101981/attachments There are n heroes and m monsters living in an isl ...
- Gym101981I Magic Potion(最大流)
Problem I. Magic Potion There are n heroes and m monsters living in an island. The monsters became v ...
- 2018icpc南京/gym101981 I Magic Potion
题意: 若干个勇士,每个勇士只能杀特定的怪物.每个勇士只能杀1个怪,但是有一些药,喝了药之后能再杀一个,每个勇士只能喝一瓶药.问你最多杀多少怪. 题解: 按照如下建图套网络流板即可. 网上有题解说套D ...
- ACM-ICPC Nanjing Onsite 2018 I. Magic Potion
题意:类似二分图匹配给的题目,不过这次在这里给出了k,表示没人可以再多一次匹配机会,这次匹配不能用上一次被匹配的对象 分析:不能用匈牙利做俩次匹配,因为俩次的最大匹配并不等价于总和的匹配,事实证明,你 ...
- HDU 4149 Magic Potion
意甲冠军: a[i] ^ x = f[i] ( i = 1...8 ) 和 ( a[1] + a[2] + ... + a[8] ) ^ x = f[9] 如今f为已知 求x 思路: 从低位到高位确 ...
- Gym - 101981I The 2018 ICPC Asia Nanjing Regional Contest I.Magic Potion 最大流
题面 题意:n个英雄,m个怪兽,第i个英雄可以打第i个集合里的一个怪兽,一个怪兽可以在多个集合里,有k瓶药水,每个英雄最多喝一次,可以多打一只怪兽,求最多打多少只 n,m,k<=500 题解:显 ...
随机推荐
- Spring、SpringMVC和Springboot的区别
spring boot就是一个大框架里面包含了许许多多的东西,其中spring就是最核心的内容之一,当然就包含spring mvc. spring mvc 是只是spring 处理web层请求的一个模 ...
- 大视频上传T级别解决方案
核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...
- css grid 随笔
原文出自Arien的博客https://www.w3cplus.com/css3/line-base-placement-layout.html 首先定义一个网格 1.可以给父容器的display属性 ...
- HDU6579 Operation
题目链接 问题分析 区间求异或和最大,比较自然的想到了线性基.而每次求一个区间的线性基显然是行不通的.我们考虑在每个位置求出首位置到当前位置的线性基.同时我们要使线性基中高位的位置所选的数尽量靠后.这 ...
- javascript 六种数据类型
js的数据类型和常见隐式转化逻辑. 一.六种数据类型 原始类型(基本类型):按值访问,可以操作保存在变量中实际的值.原始类型汇总中null和undefined比较特殊. 引用类型:引用类型的值是保存在 ...
- Java并发编程的艺术笔记(五)——Java中的锁
一.Lock接口的几个功能: 显示的获取和释放锁 尝试非阻塞的获取锁 能被中断的获取锁 超时获取锁 使用方式: Lock lock = new ReentrantLock(); lock.lock() ...
- LeetCode 92. 反转链表 II(Reverse Linked List II)
题目描述 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL, ...
- redis哨兵集群搭建
下载redis jar包redis-4.0.11.tar.gz放在/data/redis目录下 解压 命令:tar -zxvf redis-4.0.11.tar.gz 解压后如图所示 在/usr/lo ...
- 对《疯狂Spring Cloud微服务架构实战》作者的疑问
Cloud的程序都是用的内部Tomcat,即使把一个大App分成独立小块,能应付得了你们当年人力运维的大量请求涌入吗? 真不知道淘宝怎么做到的双11一直不垮?真实互联网生产环境是充斥图书市场中的所谓S ...
- Jmeter(二)关联
phpwind发贴时由于随着登陆用户的改变, verifycode是动态变化的, 因此需要用到关联. LoadRunner的关联函数是reg_save_param, Jmeter的关联则是利用后置处理 ...