您的位置:首页 > 其它

bzoj 1565 植物大战僵尸

2017-07-06 18:48 260 查看

1565: [NOI2009]植物大战僵尸

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 2697  Solved: 1234

[Submit][Status][Discuss]

Description



Input



Output

仅包含一个整数,表示可以获得的最大能源收入。注意,你也可以选择不进行任何攻击,这样能源收入为0。

Sample Input

3 2

10 0

20 0

-10 0

-5 1 0 0

100 1 2 1

100 0

Sample Output

25

HINT

在样例中, 植物P1,1可以攻击位置(0,0), P2, 0可以攻击位置(2,1)。 

一个方案为,首先进攻P1,1, P0,1,此时可以攻击P0,0 。共得到能源收益为(-5)+20+10 = 25。注意, 位置(2,1)被植物P2,0保护,所以无法攻击第2行中的任何植物。 

【大致数据规模】

约20%的数据满足1 ≤ N, M ≤ 5;

约40%的数据满足1 ≤ N, M ≤ 10;

约100%的数据满足1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。

【分析】

拓扑排序去掉环+最大权闭合子图

SBS的坑终于填掉了

【代码】

//NOI 2009 植物大战僵尸
#include<bits/stdc++.h>
#define inf 1e9
#define mp make_pair
#define ll long long
#define p(i,j) ((i-1)*m+(j))
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=600005;
queue <int> q;
bool vis[mxn],ban[mxn];
int w,n,m,S,T,ans,cnt;
vector < int > F[mxn];
struct edge {int to,next,flow;} f[mxn<<1];
int head[mxn],du[mxn],sco[mxn],num[mxn],dis[mxn];
inline void add(int u,int v,int flow)
{
f[++cnt]=(edge){v,head[u],flow},head[u]=cnt;
f[++cnt]=(edge){u,head[v],0},head[v]=cnt;
}
inline bool bfs()
{
memset(dis,-1,sizeof dis);
q.push(S),dis[S]=0;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];i;i=f[i].next)
{
int v=f[i].to,flow=f[i].flow;
if(flow>0 && dis[v]==-1)
dis[v]=dis[u]+1,q.push(v);
}
}
return dis[T]>0;
}
inline int find(int u,int low)
{
int i,j,a,sum=0;
if(u==T) return low;
for(int i=head[u];i;i=f[i].next)
{
int v=f[i].to,flow=f[i].flow;
if(flow>0 && dis[v]==dis[u]+1 && (a=find(v,min(flow,low-sum))))
{
sum+=a;
f[i].flow-=a;
if(i&1) f[i+1].flow+=a;
else f[i-1].flow+=a;
if(sum==low) return sum;
}
}
if(!sum) dis[u]=-1;
return sum;
}
inline void topsort()
{
int i,j,k;
fo(i,1,n) fo(j,1,m)
if(!du[p(i,j)]) q.push(p(i,j));
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<F[u].size();i++)
{
int v=F[u][i];
du[v]--;
if(!du[v]) q.push(v);
}
}
fo(i,1,n) fo(j,1,m)
if(du[p(i,j)]) ban[p(i,j)]=1;
}
int main()
{
int i,j,k,x,y,u,v;
scanf("%d%d",&n,&m);
S=0,T=n*m+1;
fo(i,1,n) fo(j,1,m)
{
scanf("%d",&sco[p(i,j)]);
scanf("%d",&num[p(i,j)]);
fo(k,1,num[p(i,j)])
{
scanf("%d%d",&u,&v);
u++,v++;
du[p(u,v)]++;
F[p(i,j)].push_back(p(u,v));
}
}
fo(i,1,n) fo(j,1,m-1) F[p(i,j+1)].push_back(p(i,j)),du[p(i,j)]++;
topsort();
fo(i,1,n) fo(j,1,m) if(!ban[p(i,j)])
{
int u=p(i,j);
if(sco[u]>0) add(S,u,sco[u]),ans+=sco[u];//,printf("Connect (%d,%d)\n",S,u);
else add(u,T,-sco[u]);//printf("Connect (%d,%d)\n",u,T);
for(k=0;k<F[u].size();k++)
{
int v=F[u][k];
if(ban[v]) continue;
add(v,u,inf);
// printf("Connect (%d,%d)\n",u,v);
}
}
fo(i,1,n) fo(j,1,m-1) if(!ban[p(i,j)] && !ban[p(i,j+1)])
add(p(i,j),p(i,j+1),inf);
while(bfs()) ans-=find(S,inf);
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: