• p2805 [NOI2009]植物大战僵尸


    传送门

    分析

    我们知道一个点可以保护他射程的那几个点和他左边的那个点

    我们又知道如果保护关系成环则环中的点以及这些点左面的点均是无敌的

    所以我们按保护关系连边,然后跑tarjan

    然后只要找出点数大于1的联通块中的点即可

    之后问题就转换为了求无敌点之外的点所构成图的最大权闭合子图

    注意此处是正权点连T,负权点连S,因为此处闭合图是值选一个点的同时必须选所有能到达它的点

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    #define id(x,y) (x-1)*m+y
    const int inf = 1e9+7;
    int n,m,s[80000],is[80000],Ans,S,T;
    vector<int>p[80000];
    vector<int>v[80000];
    int dfn[80000],low[80000],ist[80000],cnt,sum,belong[80000],tot[80000];
    stack<int>a;
    inline void tarjan(int x){
        low[x]=dfn[x]=++cnt;
        a.push(x);
        ist[x]=1;
        for(int i=0;i<v[x].size();i++){
          if(!dfn[v[x][i]]){
              tarjan(v[x][i]);
              low[x]=min(low[x],low[v[x][i]]);
          }else if(ist[v[x][i]]){
              low[x]=min(low[x],dfn[v[x][i]]);
          }
        }
        if(low[x]==dfn[x]){
          sum++;
          while(1){
              int u=a.top();
              a.pop();
              ist[u]=0;
              belong[u]=sum;
              tot[sum]++;
              if(u==x)break;
          }
        }
    }
    int head[2000100],w[2000100],nxt[2000100],to[2000100],ano[2000100],res;
    int level[80000],cur[2000100];
    inline void add(int x,int y,int z){
        nxt[++res]=head[x];head[x]=res;to[res]=y;w[res]=z;
        nxt[++res]=head[y];head[y]=res;to[res]=x;w[res]=0;
        ano[res]=res-1;ano[res-1]=res;
    }
    inline bool bfs(){
        memset(level,-1,sizeof(level));
        queue<int>q;
        level[S]=0;
        q.push(S);
        while(!q.empty()){
          int x=q.front();
          q.pop();
          for(int i=head[x];i;i=nxt[i])
            if(level[to[i]]==-1&&w[i]){
              level[to[i]]=level[x]+1;
              if(to[i]==T)return 1;
              q.push(to[i]);
            }
        }
        return 0;
    }
    inline int dfs(int x,int flow){
        if(x==T||!flow)return flow;
        int res=0;
        cur[x]=head[x];
        for(int i=cur[x];i;i=nxt[i]){
          cur[x]=i;
          if(level[to[i]]==level[x]+1&&w[i]){
              int f=dfs(to[i],min(flow-res,w[i]));
              w[i]-=f;
              w[ano[i]]+=f;
              res+=f;
          }
        }
        if(!res)level[x]=-1;
        return res;
    }
    int main(){
        int i,j,k,x;
        scanf("%d%d",&n,&m);
        S=n*m+10,T=S+1;
        for(i=1;i<=n;i++)
          for(j=1;j<=m;j++){
            scanf("%d",&s[id(i,j)]);
              scanf("%d",&x);
              for(k=1;k<=x;k++){
              int y,z;
              scanf("%d%d",&y,&z);
              p[id(i,j)].push_back(id(y+1,z+1)); 
            } 
          }
        for(i=1;i<=n;i++)
          for(j=1;j<=m;j++){
              if(j!=1)v[id(i,j)].push_back(id(i,j-1));
              for(k=0;k<p[id(i,j)].size();k++)
                v[id(i,j)].push_back(p[id(i,j)][k]);
          }
        for(i=1;i<=n*m;i++)
          if(!dfn[i])tarjan(i);
        for(i=1;i<=n;i++)
          for(j=m;j>0;j--)
            if(tot[belong[id(i,j)]]!=1){
              for(k=j;k>0;k--){
                is[id(i,k)]=1;
              }
              break;
            }
        for(i=1;i<=n;i++)
          for(j=1;j<=m;j++){
              if(is[id(i,j)])continue;
              if(j!=1&&!is[id(i,j-1)])add(id(i,j),id(i,j-1),inf);
              for(k=0;k<p[id(i,j)].size();k++)
                if(!is[p[id(i,j)][k]])add(id(i,j),p[id(i,j)][k],inf);
              if(s[id(i,j)]>0){
                Ans+=s[id(i,j)];
                add(id(i,j),T,s[id(i,j)]);
              }else {
                add(S,id(i,j),-s[id(i,j)]);
              }
          }
        while(bfs())while(int a=dfs(S,inf))Ans-=a;
        cout<<Ans;
        return 0;
    }
  • 相关阅读:
    EChart.js 简单入门(转)
    C# 接口的特点、接口的作用、接口的简单应用1(转)
    C# 接口的特点、接口的作用、接口的简单应用(转)
    jquery实现全选、全消、反选功能
    python函数式编程-------python2.7教程学习【廖雪峰版】(五)
    python高级-------python2.7教程学习【廖雪峰版】(四)
    python函数-------python2.7教程学习【廖雪峰版】(三)
    python基础-------python2.7教程学习【廖雪峰版】(二)
    python语言特性-------python2.7教程学习【廖雪峰版】(一)
    jquery基础研究学习【基础】
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10356810.html
Copyright © 2020-2023  润新知