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 题解:显 ...
随机推荐
- Socket 对象(内建)方法
函数 描述 服务器端套接字 s.bind() 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址. s.listen() 开始TCP监听.back ...
- 数据库范式以及ER图
数据库范式包括第一.第二.第三以及BCNF范式,关于范式的探讨,博主在知乎上看见了一篇很不错的文章,分享文中,这边就不再做阐述.地址:https://www.zhihu.com/question/24 ...
- poj2386(dfs搜索水题)
Language:Default Lake Counting Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 42069 ...
- 【Python】爬虫汇总
主要流程: 获取url下载网页从网页中找寻自己需要的保存(解析+输出)主要概念URL:分大小写统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联 ...
- JIRA7.13版本创建项目:问题类型管理(一)
1.1 创建项目 一个项目是对一系列相关问题的综合管理.在Jira 中,可以通过以下方式创建项目.首先,需要具有项目创建权限的人登录后台管理界面,然后选择项目,通过创建项目按钮进入到项目创建的界面. ...
- windows下 java使用zookeeper案例
依赖: <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeep ...
- linux面试常见
https://www.cnblogs.com/wanghuaijun/p/7421008.html 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linux内核引导时,从文件 ...
- C++入门经典-例4.8-同名的全局变量和局部变量
1:代码如下: // 4.8.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using ...
- Mysql 实用语句记录
都是工作中遇到的需求,但不是常用sql,特此记录,方便以后使用: 1.将指定列的数据拼起来存到某一列 UPDATE table_name SET b_col_name=CONCAT(b_col_nam ...
- SparseArray II
SparseArray: SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的类,目的是提高内存效率,其核心是折半查找函数(binar ...