原题链接

  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(网络流)的更多相关文章

  1. 2018ACM-ICPC亚洲区域赛南京站I题Magic Potion(网络流)

    http://codeforces.com/gym/101981/attachments 题意:有n个英雄,m个敌人,k瓶药剂,给出每个英雄可以消灭的敌人的编号.每个英雄只能消灭一个敌人,但每个英雄只 ...

  2. Magic Potion(最大流,跑两遍网络流或者加一个中转点)

    Magic Potion http://codeforces.com/gym/101981/attachments/download/7891/20182019-acmicpc-asia-nanjin ...

  3. hdu4149 Magic Potion

    Magic Potion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tota ...

  4. 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 ...

  5. Gym101981I Magic Potion(最大流)

    Problem I. Magic Potion There are n heroes and m monsters living in an island. The monsters became v ...

  6. 2018icpc南京/gym101981 I Magic Potion

    题意: 若干个勇士,每个勇士只能杀特定的怪物.每个勇士只能杀1个怪,但是有一些药,喝了药之后能再杀一个,每个勇士只能喝一瓶药.问你最多杀多少怪. 题解: 按照如下建图套网络流板即可. 网上有题解说套D ...

  7. ACM-ICPC Nanjing Onsite 2018 I. Magic Potion

    题意:类似二分图匹配给的题目,不过这次在这里给出了k,表示没人可以再多一次匹配机会,这次匹配不能用上一次被匹配的对象 分析:不能用匈牙利做俩次匹配,因为俩次的最大匹配并不等价于总和的匹配,事实证明,你 ...

  8. HDU 4149 Magic Potion

    意甲冠军: a[i] ^ x = f[i] ( i = 1...8 ) 和 ( a[1] + a[2] + ... + a[8] ) ^ x = f[9] 如今f为已知  求x 思路: 从低位到高位确 ...

  9. Gym - 101981I The 2018 ICPC Asia Nanjing Regional Contest I.Magic Potion 最大流

    题面 题意:n个英雄,m个怪兽,第i个英雄可以打第i个集合里的一个怪兽,一个怪兽可以在多个集合里,有k瓶药水,每个英雄最多喝一次,可以多打一只怪兽,求最多打多少只 n,m,k<=500 题解:显 ...

随机推荐

  1. MySQL数据库中的索引(一)——索引实现原理

    今天我们来探讨一下数据库中一个很重要的概念:索引. MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构,即索引是一种数据结构. 我们知道,数据库查询是数据库的最主要 ...

  2. protoc 编译工具

    在进行开发 protoc 之前,你需要首先在你的计算机中安装 protoc 编译工具. 下载编译工具 进入 Protocol Buffers 的源代码中然后选择发布的版本中,找到对应的版本.项目的链接 ...

  3. Socket编程-基础使用

    最后更新:2019-10-25 一 基本概念 socket, 又称为"套接字"或者"插座". 是操作系统提供的一种进程间通信机制.目前大多用于不同网络设备之间的 ...

  4. MySQ彻底删除与安装配置

    彻底删除 1.查看 MySQL 安装了哪些东西 rpm -qa |grep -i mysql 2.卸载 -.el7.x86_64 -.el7.x86_64 .noarch -.el7.x86_64 - ...

  5. 个推CTO深度解析数据智能之多维度分析系统的选型方法

    引言 前文回顾:[<数据智能时代来临:本质及技术体系要求>][2]作为本系列的第一篇文章,概括性地阐述了对于数据智能的理解以及推出了对应的核心技术体系要求: 数据智能就是以数据作为生产资料 ...

  6. C++入门经典-例2.14-使用移位运算

    1:代码如下: // 2.14.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> usin ...

  7. _parameter:解决There is no getter for property named in class java.lang.String

    我们知道在mybatis的映射中传参数,只能传入一个.通过#{参数名} 即可获取传入的值. Mapper接口文件: public int delete(int id) throws Exception ...

  8. Docker入门-介绍和安装

    Docker容器 Docker是什么 Docker最初是dotCloud公司创建人Solomon Hykes在法国期间发起的一个公司内部项目,它是基于dotCloud公司多年云服务技术的一次革新,并于 ...

  9. python3笔记十八:python列表元组字典集合文件操作

    一:学习内容 列表元组字典集合文件操作 二:列表元组字典集合文件操作 代码: import pickle  #数据持久性模块 #封装的方法def OptionData(data,path):    # ...

  10. java操作poi生成excel.xlsx(设置下拉框)下载本地和前端下载

    需求:导入excel表格,如果excel有错误,将错误的地方标红,在把数据以excel的形式写出,供用户下载解决方案:1.以实体类的方式接收excel并解析(创建两个集合一个接收正常的数据一个接收错误 ...