原题链接

  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. 在linux 下配置firewalld

    查看firewalld 是否开始与运行 以下两种方式都可以 systemctl status firewalld.service firewall-cmd --state 查看所有打开的端口 以下两种 ...

  2. Linux命令-文本编辑(二)

    Linux命令-文本编辑(二) Linux mtype命令 mtype为mtools工具指令,模拟MS-DOS的type指令,可显示MS-DOS文件的内容. 语法: mtype [-st][文件] 参 ...

  3. hexo的流程

    1.基于node 的npm包管理工具2.npm install -g hexo(hexo-cli)3.下载的资源是国外的可能比较慢,可以使用淘宝镜像(代理的仓库)npm install -g hexo ...

  4. cursor url 自定义鼠标样式

    cursor可以自定义鼠标,写法是cursor:url(“图片路径”),pointer; url:需使用的自定义光标的 URL.图片类型需要是.cur或.ani和jpg,png等格式的(.cur或.a ...

  5. linux 下使用命令查看jvm信息

    java程序员除了编写业务代码之外,特别是项目上线之后,更需要关注的是系统的性能表现,这个时候就需要了解一下jvm的性能表现了,可以借助于java虚拟机自带的一些分析工具,主要有三个常用的命令. 1. ...

  6. ionic1使用imagepicker在安卓手机上闪退问题

    在上一篇文章中,提到了如何在ionic1中使用imagepicker插件,并且实现该插件显示中文(汉化)问题有兴趣可以看看:ionic1使用ImagePicker插件并且显示中文(汉化) 1.这次要解 ...

  7. linux 系统的 cache 过大,解决方案

    linux buff/cache过大,清理脚本 2018年06月20日 13:44:53 taozhe666 阅读数:6500   三条指令: sync echo 1 > /proc/sys/v ...

  8. Zookeeper(二)数据模型

    Zookeeper数据模型ZNode 问题 ZK的数据模型ZNodes是什么样的: 树形结构,每个叶子节点都存储着数据,且可挂载子节点: 路径作为叶子节点名称,数据作为叶子节点内的数据: Znode可 ...

  9. LeetCode 93. 复原IP地址(Restore IP Addresses)

    题目描述 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 示例: 输入: "25525511135" 输出: ["255.255.11.135&qu ...

  10. 五一 DAY 7

    五一  DAY 7 P1514 引水入城 P1311 选择客栈 题解: P1315 观光公交 题解: 设 wait i 为最晚到达的旅客 arrive i 为到达i 的时刻 arrive i =max ...