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 题解:显 ...
随机推荐
- vscode存盘时格式化
1.文件->首选项->设置
- redis string类型设置过期时间后 再进行set操作,会清除过期时间
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qq_41756437/article/d ...
- ASP.NET大文件上传断点续传解决方案
HTML部分 <%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx. ...
- HDU 6438 Buy and Resell ( 2018 CCPC 网络赛 && 贪心 )
题目链接 题意 : 给出一些数.你可以从左到右对这些数进行三种操作花费 Ai 买入东西.以 Ai 价格卖出你当前有的东西.或者什么都不做.现在问你可以获取的最大利益是多少? 分析 : 和 CF 867 ...
- 【BZOJ3261】最大异或和(可持久化Trie)
题意: 思路:可持久化Trie板子题,支持序列插入和询问 #include<bits/stdc++.h> using namespace std; typedef long long ll ...
- CodeForces 349B--Color the Fence(贪心)
B. Color the Fence time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- Java并发编程的艺术笔记(七)——CountDownLatch、CyclicBarrier详解
一.等待多线程完成的CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作,像加强版的join.(t.join()是等待t线程完成) 例: (1)开启多个线程 ...
- .item布局设置分割线
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=" ...
- Vagrant基本命令详解
正在学习Docker Swarm,接触到了Vagrant.Vagrant是一个创建虚拟机的技术,可以把它认为是一个Vmware,它让我们可以通过代码的方式快速地.可重复地创建针对不同虚拟环境的虚拟机, ...
- SpringMvc中@PathVariable注解简单的用法
@PathVariable /** * @PathVariable 可以来映射 URL 中的占位符到目标方法的参数中. * @param id * @return */ jsp页面请求 <a h ...