zoukankan      html  css  js  c++  java
  • BZOJ 1565 NOI2009 植物大战僵尸

    1565: [NOI2009]植物大战僵尸

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 2922  Solved: 1332
    [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 。

    Source

    这道题是对最大闭合子图的应用

    环上的点肯定是不能吃的,我们用topsort进行去环,求出答案即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    inline int read()
    {
     int x=0;int f=1;char ch=getchar();
     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
     return x*f;
    }
    struct node
    {
     int y;
     int next;
     int back;
     int flow;
    }e[200100],ee[200100];
    int linkk[200010];
    int linkkk[200000];
    int id[100010];
    int f[100010];
    int summ=0;
    int q[100101];
    int flag[100010]={};
    int n,m,head,tail,len,st,end;
    int getpoint(int x,int y)
    {
     return x*m-m+y;
    }
    void insert1(int xx,int yy)
    {
     ee[++len].y=yy;
     ee[len].next=linkkk[xx];
     linkkk[xx]=len;
     ee[len].flow=4728479;
    }
    void insert(int xx,int yy,int vv)
    {
     e[++len].y=yy;
     e[len].flow=vv;
     e[len].next=linkk[xx];
     e[len].back=len+1;
     linkk[xx]=len;
     e[++len].y=xx;
     e[len].next=linkk[yy];
     e[len].flow=0;
     e[len].back=len-1;
     linkk[yy]=len;
    }
    void topsort()//去环
    {
      tail=0;
      head=0;
     for(int i=1;i<=n*m;i++)
     {
      if(!id[i]) q[++tail]=i,flag[i]=1;
     }
     while(head<tail)
     {
      int tn=q[++head];
      for(int i=linkkk[tn];i;i=ee[i].next)
      {
       id[ee[i].y]--;
       if(!id[ee[i].y])
       {
        q[++tail]=ee[i].y;
        flag[ee[i].y]=1;
       }
      }
     }
    }
    void buildtu()
    {
     len=0;
     for(int i=1;i<=n*m;i++)
     {
      if(flag[i]==0) continue;
      if(f[i]>0) insert(st,i,f[i]),summ+=f[i];
      if(f[i]<0) insert(i,end,-f[i]);
      for(int j=linkkk[i];j;j=ee[j].next)
      {
        if(flag[ee[j].y]==0) continue;
       insert(ee[j].y,i,624726488);
      }
     }
    }
    int level[10100];
    bool vis[10010];
    int getlevel()
    {
     memset(level,-1,sizeof(level));
     memset(q,0,sizeof(q));
     tail=head=0;
     level[st]=0;
     q[++tail]=st;
     while(head<tail)
     {
      int tn=q[++head];
      for(int i=linkk[tn];i;i=e[i].next)
      {
        if(level[e[i].y]==-1&&e[i].flow!=0)
        {
         q[++tail]=e[i].y;
         level[e[i].y]=level[tn]+1;
        }        
      }
     }
     return level[end]>-1;
    }
    int getmaxflow(int stt,int flow)
    {
     int maxflow=0;
     int d=0;
     if(stt==end) return flow;
     for(int i=linkk[stt];i&&maxflow<flow;i=e[i].next)
     {
      if(level[e[i].y]==level[stt]+1&&e[i].flow)
      {
       if(d=getmaxflow(e[i].y,min(flow-maxflow,e[i].flow)))
       {
        maxflow+=d;
        e[i].flow-=d;
        e[e[i].back].flow+=d;
       }
      }
     }
     if(!maxflow) level[stt]=-1;
     return maxflow;
    }
    void dinic()
    {
     int ans=0;
     int sum;
     while(getlevel())
     {
      while(sum=getmaxflow(st,31763786)) ans+=sum; 
     }
     cout<<summ-ans<<endl;
    }
    int main()
    {
     cin>>n>>m;
     st=0;
     end=n*m+1;
     for(int i=1;i<=n*m;i++)
     {
      f[i]=read();
      int w;
      cin>>w;
      int now;
      int a,b;
      while(w--)
      {
       a=read()+1;
       b=read()+1;
       now=getpoint(a,b);
       insert1(i,now);
       id[now]++;
      }
      if(i%m==0) continue;
      insert1(i+1,i);id[i]++;
     }
     topsort();
     buildtu();
     dinic();
     return 0;
    }
    

      

  • 相关阅读:
    (转)AS3中实现卡马克卷轴算法
    (转)flash位图缓存cacheAsBitmap
    (转)addFrameScript函数的纠结
    (转)flash安全策略文件
    (转)脏矩形技术学习
    (转)stopImmediatePropagation 和stopPropagation的区别
    (转)flash对象池技术
    揭开嵌入式C面试题背后的玄机
    一次遍历找链表倒数第n个节点
    N!的尾部连续0的个数
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/7977292.html
Copyright © 2011-2022 走看看