BZOJ_1565_[NOI2009]_植物大战僵尸_(Tarjan+最大流+最大权闭合图)
2016-04-28 09:48
465 查看
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1565
n*m的矩阵,可以种植植物,僵尸从图的右边进入吃植物.前面的植物可以保护后面的植物,还有一些植物会保护特定位置的其他植物.这里保护的意思是:a保护b等价于僵尸必须先吃a,才能吃b.每个植物有一个价值(可正可负),问僵尸能获得的最大价值.
1565: [NOI2009]植物大战僵尸
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1972 Solved: 917
[Submit][Status][Discuss]
Description
#include<cstdio> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<vector> #include<iostream> #define rep(i,n) for(int i=0;i<(n);i++) #define for1(i,a,n) for(int i=(a);i<=(n);i++) #define read(a) a=getnum() #define CC(i,a) memset(i,a,sizeof(i)) using namespace std; const int maxn=(20*30)+5,INF=0x7fffffff; int n,m,W,N; int w[maxn]; bool mark[maxn]; vector <int> e[maxn]; inline int getnum() { int r=0,k=1;char c;for(c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') k=-1; for(;c>='0'&&c<='9';c=getchar()) r=r*10+c-'0'; return r*k; } struct Tarjan { int idx; int dfn[maxn],low[maxn]; bool ins[maxn]; stack <int> s; void dfs(int u) { s.push(u); ins[u]=true; dfn[u]=low[u]=idx++; rep(i,e[u].size()) { int v=e[u][i]; if(!dfn[v]) { dfs(v); low[u]=min(low[u],low[v]); } else if(ins[v]) { low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { ins[u]=false; if(s.top()==u) s.pop(); else { int top; while((top=s.top())!=u) { s.pop(); ins[top]=false; mark[top]=true; } s.pop(); mark[top]=true; } } } }tarjan; struct Flow { int level[maxn],iter[maxn]; struct edge { int to,cap,rev; edge() {} edge(int a,int b,int c):to(a),cap(b),rev(c) {} }; vector <edge> g[maxn]; void add_edge(int from,int to,int cap) { g[from].push_back(edge(to,cap,g[to].size())); g[to].push_back(edge(from,0,g[from].size()-1)); } void bfs(int s) { CC(level,-1); level[s]=0; queue <int> q; q.push(s); while(!q.empty()) { int t=q.front(); q.pop(); rep(i,g[t].size()) { edge e=g[t][i]; if(e.cap>0&&level[e.to]<0) { level[e.to]=level[t]+1; q.push(e.to); } } } } int dfs(int u,int t,int f) { if(u==t) return f; for(int &i=iter[u];i<g[u].size();i++) { edge &e=g[u][i]; if(e.cap>0&&level[e.to]>level[u]) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; g[e.to][e.rev].cap+=d; return d; } } } return 0; } int max_flow(int s,int t) { int flow=0; bfs(s); while(level[t]>0) { int f; CC(iter,0); while((f=dfs(s,t,INF))>0) flow+=f; bfs(s); } return flow; } }flow; void pro(int u) { if(mark[u]) return; mark[u]=true; rep(i,e[u].size()) { pro(e[u][i]); } } void solve() { for1(i,1,N) { if(!tarjan.dfn[i]) { tarjan.dfs(i); } } for1(i,1,N) { if(mark[i]) { rep(j,e[i].size()) { pro(e[i][j]); } } } for1(i,1,N) { if(mark[i]) continue; if(w[i]>0) { W+=w[i]; flow.add_edge(0,i,w[i]); } else { flow.add_edge(i,N+1,-w[i]); } rep(j,e[i].size()) { flow.add_edge(e[i][j],i,INF); } } printf("%d\n",W-flow.max_flow(0,N+1)); } void init() { read(n); read(m); N=n*m; for1(i,1,n) { for1(j,1,m) { int u=(i-1)*m+j,a; read(w[u]); read(a); while(a--) { int x,y; read(x); read(y); int v=x*m+y+1; e[u].push_back(v); } if(j>1) { e[u].push_back(u-1); } } } } int main() { #ifndef ONLINE_JUDGE freopen("plant.in","r",stdin); freopen("plant.out","w",stdout); #endif init(); solve(); #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); system("plant.out"); #endif return 0; }View Code
相关文章推荐
- [react native] navigator过渡卡顿问题
- c语言开发窗口应用程序
- 输入n个整数,找出其中最小的k个数
- Qt 4.8.6 X11、embeded x86(qvfb运行 )、embeded arm各个版本编译总结
- C++ 使用C库 extern "C"
- VS2013命令行界面查看虚函数的内存布局
- ZeroMQ之Push与Pull (Java)
- redhat开机不启动桌面登录程序
- JAVA——守护线程或用户线程(setDaemon)
- unity 技巧1
- 相对路径和绝对路径的理解以及android需要绝对路径的原因
- 服务器端select I/O多路复用模型
- \bibliography 包含多个.bib文件
- GridVeiw 使用
- asp.net mvc 中的 controller和asp.net web api 的apicontroller有什么区别?(转)
- 华为的绩效管理:减人、增 效、加薪
- Error:Execution failed for task ‘:app:clean’.
- Ubuntu on Windows 10工作方式全解析
- 构造方法
- Node.js EventEmitter 事件监听