您的位置:首页 > 其它

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 MB
Submit: 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

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: