【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的矩阵,每个位置都有一个植物.每个植物都有一个价值(可以为负),以及一些它可以攻击的位置.从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡.僵尸每到一个位 ...
随机推荐
- method 'redisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError
spring boot 整合redis是报了如下错误 org.springframework.beans.factory.UnsatisfiedDependencyException: Error c ...
- Codeforces 724 G Xor-matic Number of the Graph 线性基+DFS
G. Xor-matic Number of the Graph http://codeforces.com/problemset/problem/724/G 题意:给你一张无向图.定义一个无序三元组 ...
- SAP ERP classification和C4C的同步
在ERP里创建两个characteristic: 创建一个class包这两个characteristic.Class type 002意为该class能用于equipment. replicate到C ...
- JNI接口的使用(简单版)
详见 http://b6ec263c.wiz03.com/share/s/2SX2oY0nX4f32CY5ax1bapaL2Qtc5q0tIQjG2yfwaU1MX4Ye
- UVA 536 TreeRocvery 树重建 (递归)
根据先序历遍和中序历遍输出后序历遍,并不需要真的建树,直接递归解决 #include<cstdio> #include<cstring> ; char preOrder[N]; ...
- Android(java)学习笔记108:Android的Junit调试
1. Android的Junit调试: 编写android应用的时候,往往我们需要编写一些业务逻辑实现类,但是我们可能不能明确这个业务逻辑是否可以成功实现,特别是逻辑代码体十分巨大的时候,我们不可能一 ...
- 【转】iOS学习笔记(十五)——数据库操作(SQLite)
SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库.SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百K的 ...
- 2018.4.13 用java配置/生成Xml文件 结合IO流知识点
自己创建本地文件Hello.txt 里面有数据 小明/23/增城/广东 小花/12/浦东/上海 StudentManager.java package com.lanqiao.dmeo7; impor ...
- gearmand安装
下载 https://github.com/gearman/gearmand/releases 解压,进入目录 sudo ./configure make sudo make install 问题1: ...
- J.U.C知识点梳理
java.util.concurrent : 提供了并发编程的解决方案 1.CAS 是java.util.concurrent.atomic包的基础 2.AQS是java.util.concurren ...