【Luogu】P2805植物大战僵尸(拓扑排序+最大流)
这题数据xie强qwq。拓扑用的那个图建反了得80.
一眼看出(个屁,题解上都说一眼看出,然而我还是太蒻了)这是个最大权闭合图。从被保护植物向保护植物连边,然后跑最大流,用正点权和减去。
哦最大权闭合图我会。
准备开始码。
等等题解下面好像还写东西?
emmmm有环,所以拓扑排序……
好,我写……
写了半小时,调了两发过样例交了。
wtf80?
然后想了半小时,想不出来为什么qwq、
然后手推。
不对呀数据给的这张图拓扑不动呀?
然后想了想,觉得不对呀……应该反着拓扑才对……
然后翻题解
emm果然是在反向图上拓扑。
emmmmmm
于是沉吟良久改了四句话,然后就A了。
qwqqqqqq。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<algorithm>
#include<queue>
#define maxn 12000
#define maxm 1000000
using namespace std; inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} int n,m;
inline int count(int i){ return i&?i+:i-; }
inline int calc(int i,int j){ return (i-)*m+j; }
int dfn[maxn];
bool vis[maxn];
int list[maxn];
int Start,End;
int indl[maxn];
bool ext[maxn];
queue<int>f; struct Pic{
struct Edge{
int next,to,val;
}edge[maxm];
int head[maxn],num;
Pic(){memset(head,,sizeof(head)); num=; }
inline void addedge(int from,int to,int val){
edge[++num]=(Edge){head[from],to,val};
head[from]=num;
}
inline void add(int from,int to,int val){
addedge(from,to,val);
addedge(to,from,);
}
bool bfs(){
memset(vis,,sizeof(vis));
dfn[Start]=; vis[Start]=;
queue<int>q; q.push(Start);
while(!q.empty()){
int from=q.front(); q.pop();
for(int i=head[from];i;i=edge[i].next){
int to=edge[i].to;
if(vis[to]||edge[i].val==) continue;
vis[to]=; dfn[to]=dfn[from]+;
q.push(to);
}
}
return vis[End];
}
int dfs(int x,int val){
if(x==End||val==) return val;
int flow=; vis[x]=;
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(edge[i].val==||dfn[to]!=dfn[x]+) continue;
int now=dfs(to,min(val,edge[i].val));
edge[i].val-=now; edge[count(i)].val+=now; val-=now; flow+=now;
if(val<=) break;
}
if(val!=flow) dfn[x]=-;
return flow;
}
inline int maxflow(){
int ans=;
while(bfs()){
memset(vis,,sizeof(vis));
for(int i=Start;i<=End;++i) list[i]=head[i];
int now=dfs(Start,0x7fffffff);
if(now==) break;
ans+=now;
}
return ans;
}
}Old,New;
int sco[][];
int sum; int main(){
n=read(),m=read();
for(int i=;i<=n;++i)
for(int j=;j<m;++j){
int x=calc(i,j+);
Old.addedge(x,calc(i,j),);
indl[calc(i,j)]++;
//Old.addedge(calc(i,j),x,0);
//indl[x]++;
}
for(int i=;i<=n;++i)
for(int j=;j<=m;++j){
sco[i][j]=read();
int x=read();
for(int k=;k<=x;++k){
int a=read()+,b=read()+;
int opt=calc(a,b);
Old.addedge(calc(i,j),opt,);
indl[opt]++;
//Old.addedge(opt,calc(i,j),0);
//indl[calc(i,j)]++;
}
}
for(int i=;i<=n*m;++i)
if(indl[i]==){
f.push(i);
ext[i]=;
}
while(!f.empty()){
int from=f.front(); f.pop();
for(int i=Old.head[from];i;i=Old.edge[i].next){
int to=Old.edge[i].to;
indl[to]--;
if(indl[to]==){
ext[to]=;
f.push(to);
}
}
}
End=n*m+;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j){
int ret=calc(i,j);
if(ext[ret]==) continue;
if(sco[i][j]>) sum+=sco[i][j];
if(sco[i][j]>) New.add(Start,ret,sco[i][j]);
else New.add(ret,End,-sco[i][j]);
for(int k=Old.head[ret];k;k=Old.edge[k].next){
int to=Old.edge[k].to;
New.add(to,ret,0x7fffffff);
}
}
int ans=New.maxflow();
printf("%d",sum-ans);
return ;
}
【Luogu】P2805植物大战僵尸(拓扑排序+最大流)的更多相关文章
- P2805 [NOI2009]植物大战僵尸 (拓扑排序 + 最小割)
题意:N*M的矩阵 每个点上都有一颗植物 僵尸只能从每一行的最右边向左进攻 每个植物有攻击范围 可以保护在攻击范围内的植物 同时每一颗植物也保护他左边的植物 摧毁每个植物能获得价值 如果这个植物被保护 ...
- 【BZOJ-1565】植物大战僵尸 拓扑排序 + 最小割
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1972 Solved: 917[Submit][Statu ...
- BZOJ 1565 植物大战僵尸(拓扑排序+最大权闭合子图)
图中的保护关系就类似于最大权闭合子图.即你想杀x,你就一定要杀掉保护x的点,那么把x向保护它的点连边.那么题目就转化成了最大权闭合子图的问题. 但是这个图有点特殊啊... 考虑有环的情况,显然这个环以 ...
- 【bzoj1565】[NOI2009]植物大战僵尸 拓扑排序+最大权闭合图
原文地址:http://www.cnblogs.com/GXZlegend/p/6808268.html 题目描述 输入 输出 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何 ...
- 洛谷 - P2805 - 植物大战僵尸 - 最大流 - 最大权闭合子图
https://www.luogu.org/problemnew/show/P2805 最大权闭合子图的特点是,假如你要选一个结点,则要先选中它的所有子节点.正权连S负权连T,容量为绝对值,原图有向边 ...
- BZOJ_1565_[NOI2009]_植物大战僵尸_(Tarjan+最大流+最大权闭合图)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1565 n*m的矩阵,可以种植植物,僵尸从图的右边进入吃植物.前面的植物可以保护后面的植物,还有 ...
- Luogu P1113 杂务 【拓扑排序】 By cellur925
题目传送门 这题我们一看就知道是拓扑排序,然而在如何转化问题上花了大工夫,一个小时后最后还是无奈看了题解qwq. 显然我们可以对于每个任务,从他的前导任务到他连一条边,最后我们可以得到一个DAG.在这 ...
- luogu 3441 [POI2006]MET-Subway 拓扑排序+思维
Description 给出一棵N个结点的树,选择L条路径,覆盖这些路径上的结点,使得被覆盖到的结点数最多. Input 第一行两个正整数N.L(2 <= N <= 1,000,000, ...
- P2805 [NOI2009]植物大战僵尸(最小割+拓扑排序)
题意: n*m的矩阵,每个位置都有一个植物.每个植物都有一个价值(可以为负),以及一些它可以攻击的位置.从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡.僵尸每到一个位 ...
随机推荐
- [中文翻译] ASP.NET 5 简介(Introducing ASP.NET 5,原作ScottGu 2015/2/23)
本文出处 [中文翻译] ASP.NET 5 简介(Introducing ASP.NET 5,原作ScottGu 2015/2/23) 这是我的文章备份 http://www.dotblogs.co ...
- 如何处理错误消息Please install the Linux kernel header files
Please install the Linux kernel "header" files matching the current kernel 当我启动minilkube时遇 ...
- WebClient UI和Tomcat的启动器
WebClient UI 我们在WebClient UI的开发工具里点了Test按钮, 会在浏览器以测试模式打开选中的view.这背后发生了什么事?注意浏览器地址栏的bspwd_cmp_test,这是 ...
- UVA 11853 - Paintball 战场(dfs)
题意:有n个敌人,每个敌人有一个攻击范围,问你是否存在从西边到东边的路径,如果存在,输出入点和出点最靠北的坐标. 把每个敌人看出一个圆,从上往下跑dfs连通,如果到达底部,那么无解.要求出最靠北的坐标 ...
- cdoj 414 八数码 (双向bfs+康拓展开,A*)
一道关乎人生完整的问题. DBFS的优越:避免了结点膨胀太多. 假设一个状态结点可以扩展m个子结点,为了简单起见,假设每个结点的扩展都是相互独立的. 分析:起始状态结点数为1,每加深一层,结点数An ...
- C08 C语言预处理命令
目录 宏定义 文件包含 条件编译 预处理命令 C语言的预处理:在编译之前进行的处理,不进行编译. C语言的预处理功能有: 宏定义 文件包含 条件编译 预处理命令以符号“#”开头.. 宏定义 不带参数的 ...
- leetcode-16-greedyAlgorithm
455. Assign Cookies 解题思路: 先将两个数组按升序排序,然后从后往前遍历,当s[j] >= g[i]的时候,就把s[j]分给g[i],i,j都向前移动,count+1;否则向 ...
- python寻找模块的路径顺序
>>> import sys >>> sys.path ['', '/Library/Frameworks/Python.framework/Versions/3. ...
- alex 推荐的书
这两本书不错, 追风筝的人<白鹿原>~~~反天不错~~~可以看下.14:27:22AndyZhang 2018-1-29 14:27:22 改变人的东西 读书.看电影.旅行.经历各种事 ...
- Python并发(一)
假设我们要从一个网站用Python程序下载5张图片,最传统的思路就是写个for循环挨个挨个下载,但是这样做有个缺点,就是除了第一张,每张图片都必须等待前一张图片下载完毕后,才可以开始下载.由于网络有很 ...