ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P2805

2022-07-20 08:01:21  阅读:129  来源: 互联网

标签:植物 le 能源 text 源点 子图 P2805


前置知识:\(\text{tarjan}\) 缩点或拓扑排序判环

至少要有一种方法判环。

前置知识:最大权闭合子图

可以看第一篇题解的讲述或者先写一下模板题

题意:

P2805 [NOI2009] 植物大战僵尸

在大小为 \(N\times M\) 的网格图上,每个点都有一株植物。
每株植物都有一个能源值,以及其防御位置集合,能源不保证非负。
可以从地图右侧开始攻击,不能经过未被消灭的植物的防御集合。
求问攻击最大收益。

\(1\le N\le 20,1\le M\le 30,\left|\text{Score}\right| \le 4000\)。

题解:

最大权闭合子图的最小割建图可以引申到此题上。
设点 \(i\) 权值为 \(v_i\),源点和汇点 \(s,t\)。

  • 对于每个点 \(u\)
    • 若 \(v_u>0\),从源点向 \(u\) 连一条容量为 \(s_u\) 的边。\(s \xrightarrow{v_u} u\)。
    • 若 \(v_u<0\),从 \(u\) 向汇点连一条容量为 \(s_u\) 的边。\(u \xrightarrow{v_u} t\)。
  • 对于图中原有的边 \(u \to v\),两点之间连一条容量无限大的边。\(u \xrightarrow{\text{inf}} v\)。

由此题的条件:攻击一株植物要先消灭其右边和保护此植物的所有植物,可以发现这和最大闭合子图类似。
所以,先将所有植物按其能源值正负分别向源点或汇点连容量为能源值绝对值的边。
再将每株植物向保护其的所有植物连容量无限大的边,跑最大权闭合子图即可。
最后的答案就是所有正能源值之和减去最大流

但是可能会出现植物无敌的情况,比如两株植物互相保护。
所以要先在建出的图的反图上跑拓扑排序,或是 \(\text{tarjan}\) 找环后从环上点出发跑 \(\text{BFS}\),找到无敌的点。
在网络流建图时,除去无敌的点,而且正能源值之和中也不包括无敌点的能源值。

代码:

#include <bits/stdc++.h>
#define id(x,y) ((x-1)*m+y)
#define V e[i].v
using namespace std;
int rd(){
  int w=0,v=1;
  char c=getchar();
  while(c<'0'||c>'9'){
    if(c=='-')
      v=-1;
    c=getchar();
  }while(c>='0'&&c<='9'){
    w=(w<<1)+(w<<3)+(c&15);
    c=getchar();
  }return w*v;
}const int N=2e5,INF=2e9;
int n,m,st,ed,ans;
int a[1001][1001];
struct E{int v,w,nt;}e[N];
int fir[N],c=1;
void I(int u,int v,int w){
  e[++c]=(E){v,w,fir[u]};
  fir[u]=c;
  e[++c]=(E){u,0,fir[v]};
  fir[v]=c;
}int cur[N],d[N];
queue <int>q;
vector <int>g[N];
bool bfs(){
  for(int i=0;i<=ed;i++){
    cur[i]=fir[i];
    d[i]=0;
  }q.push(st);
  d[st]=1;
  while(!q.empty()){
    int u=q.front();
    q.pop();
    for(int i=fir[u];i;i=e[i].nt)
      if(e[i].w&&!d[V]){
        q.push(V);
        d[V]=d[u]+1;
      }
  }return d[ed];
}int dfs(int u,int fl){
  if(u==ed) 
    return fl;
  int f,s=0;
  for(int i=cur[u];i;i=e[i].nt){
    cur[u]=i;
    if(e[i].w&&d[V]==d[u]+1){
      f=dfs(V,min(e[i].w,fl));
      e[i].w-=f;
      e[i^1].w+=f;
      fl-=f;s+=f;
      if(!fl) break;
    }
  }if(!s) d[u]=0;
  return s;
}int dinic(){
  int ans=0;
  while(bfs())
    ans+=dfs(st,INF);
  return ans;
}int dfn[N],low[N];
int tim,xs,si[N];
bool in[N],tag[N];
int sta[N],tp,now;
void tarjan(int u){
  dfn[u]=low[u]=++tim;
  in[sta[++tp]=u]=1;
  for(auto v:g[u])
    if(!dfn[v]){
      tarjan(v);
      low[u]=min(low[u],low[v]);
    }else if(in[v])
      low[u]=min(low[u],dfn[v]);
  if(dfn[u]==low[u]){
    xs++;now=tp;
    while(sta[tp+1]!=u){
      in[sta[tp--]]=0;
      si[xs]++;
    }if(si[xs]<=1) return ;
    for(int i=tp+1;i<=now;i++){
      tag[sta[i]]=1;
      q.push(sta[i]);
    }
  }
}int main(){
  freopen("test.in","r",stdin);
  n=rd(),m=rd();
  ed=n*m*2;
  for(int i=1;i<=n;i++)
    for(int j=2;j<=m;j++)
      g[id(i,j)].push_back(id(i,j-1));
  for(int i=1;i<=n;i++)
    for(int j=1,k,x,y;j<=m;j++){
      a[i][j]=rd();k=rd();
      while(k--){
        x=rd()+1,y=rd()+1;
        g[id(i,j)].push_back(id(x,y));
      }
    }
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      if(!dfn[id(i,j)])
        tarjan(id(i,j));
  while(!q.empty()){
    int u=q.front();
    q.pop();
    for(auto i:g[u]){
      if(!tag[i]){
        tag[i]=1;
        q.push(i);
      }
    }
  }for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++){
      if(tag[id(i,j)])
        continue;
      if(a[i][j]>0)
        I(st,id(i,j),a[i][j]),ans+=a[i][j];
      if(a[i][j]<0)
        I(id(i,j),ed,-a[i][j]);
    }
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      if(!tag[id(i,j)])
        for(int k:g[id(i,j)])
          if(!tag[k])
            I(k,id(i,j),INF);
  cout<<ans-dinic();
  return 0;
}

标签:植物,le,能源,text,源点,子图,P2805
来源: https://www.cnblogs.com/AIskeleton/p/16496473.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有