bzoj 1565 [NOI2009]植物大战僵尸 解题报告

1565: [NOI2009]植物大战僵尸

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 2161  Solved: 1000
[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

 
[ Submit][ Status][ Discuss]


HOME Back

————————————————我是分割线——————————————————————————

好题啊好题

这题折腾了三天,差点没吐出血来。

先拓扑排序求环,把环删掉。

之后重建图求最大权闭合子图,把一个植物向保护它的植物连边,跑一遍网络流即可。

第一次只过了4个点。不明所以。

换方法重写了拓扑,在网络流中加限制乱搞。

终于90,但第九个点一直RE,最后发现数组开小了。这题最多600个点,但边数组一直开到800005才A了。TAT~

  1 /*
  2     Problem: bzoj 1565 [NOI2009]植物大战僵尸
  3     OJ:         bzoj
  4     User:    S.B.S.
  5     Time:     264 MS
  6     Memory:     13884 KB
  7     Length:  6934 B
  8 */
  9 #include<iostream>
 10 #include<cstdio>
 11 #include<cstring>
 12 #include<cmath>
 13 #include<algorithm>
 14 #include<queue>
 15 #include<cstdlib>
 16 #include<iomanip>
 17 #include<cassert>
 18 #include<climits>
 19 #include<functional>
 20 #include<bitset>
 21 #include<vector>
 22 #include<list>
 23 #define F(i,j,k) for(int i=j;i<=k;++i)
 24 #define M(a,b) memset(a,b,sizeof(a))
 25 #define FF(i,j,k) for(int i=j;i>=k;i--)
 26 #define inf 0x3f3f3f3f
 27 #define maxm 1001
 28 #define mod 998244353
 29 //#define LOCAL
 30 using namespace std;
 31 int read(){
 32     int x=0,f=1;char ch=getchar();
 33     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 34     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 35     return x*f;
 36 }
 37 int n,m;
 38 int mp[2000];
 39 struct EDGE
 40 {
 41     int from;
 42     int to;
 43     int value;
 44     int next;
 45 }e[800005];
 46 int head[4001];
 47 int v[4001],in[4001],out[4001];
 48 int tot=1;
 49 inline void addedge(int u,int v,int w)
 50 {
 51     e[++tot].from=u;
 52     e[tot].to=v;
 53     e[tot].value=w;
 54     e[tot].next=head[u];
 55     head[u]=tot;
 56 //    tot++;
 57 }
 58 //bool kan[2000][2000];
 59 int ans=0;
 60 //inline int at(int x,int y)
 61 //{
 62 //    return m*x+y+1;
 63 //}
 64 //int stk[4001],top=0;
 65 //inline void topsort()
 66 //{
 67 //    int temp[4001];M(temp,0);
 68 //    F(i,1,m*n) temp[i]=in[i];
 69 //    F(i,1,m*n){
 70 //        if(in[i]==0){
 71 //            stk[top]=i;
 72 ////            cout<<i<<"********"<<endl;
 73 //            top++;
 74 //        }
 75 //    }
 76 ////    cout<<top<<": "<<endl;
 77 ////    F(i,0,top-1) cout<<stk[i]<<" ";cout<<endl;
 78 //    while(top!=0){
 79 //        top--;int u=stk[top];
 80 //        for(int i=head[u];i!=-1;i=e[i].next)
 81 //        {
 82 //            in[e[i].to]--;
 83 //            if(in[e[i].to]==0){
 84 //                stk[top]=e[i].to;
 85 //                top++;
 86 //            }
 87 //        }
 88 //    }
 89 //    F(i,1,m*n){
 90 //        if(in[i]!=0){
 91 //            stk[top]=i;
 92 //            top++;
 93 //        }
 94 //    }
 95 //    while(top!=0){
 96 //        top--;int u=stk[top];
 97 //        temp[u]=-1;out[u]=-1;
 98 //        v[u]=0;
 99 //    }
100 //    F(i,1,m*n) in[i]=temp[i];
101 //    return;
102 //}
103 inline void add(int u,int v,int w)
104 {
105     addedge(u,v,w);
106     addedge(v,u,0);
107     ++in[u];
108     return;
109 }
110 int map[4001];
111 int S,T;
112 bool ok()
113 {  
114     F(i,S,T) if(map[i]!=-2) map[i]=-1;
115     int que[4001];  
116     int hd=0,tl=0;  
117     que[tl++]=S;  
118     map[S]=1;  
119     while (hd<tl){  
120         int u=que[hd++];  
121         for(int i=head[u];i;i=e[i].next)
122         {  
123             if(map[e[i].to]==-1&&e[i].value)
124             {  
125                 map[e[i].to]=map[u]+1;  
126                 que[tl++]=e[i].to;  
127             }  
128         }  
129     }  
130 //    if (map[T]!=-1) return true;  
131 //    else return false;  
132     return map[T]>0;
133 }  
134 int cur[4000];
135 int zeng(int k,int now)
136 {  
137     if (k==T) return now;  
138     int r=0;  
139     for (int i=cur[k];i&&now>r;i=e[i].next)
140     {  
141         if (map[k]+1==map[e[i].to]&&e[i].value)
142         {  
143             int t=zeng(e[i].to,min(now-r,e[i].value));  
144             e[i].value-=t;e[i^1].value+=t;r+=t;  
145             if(e[i].value) cur[k]=i;//***
146 //            cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<t<<endl;
147         }  
148     }  
149     if (!r) map[k]=-1;  
150     return r;  
151 }  
152 int dinic()  
153 {  
154     int r=0,t;  
155     M(cur,0);
156     while (ok()){
157         for(int i=S;i<=T;++i) cur[i]=head[i];
158         r+=zeng(S,inf);
159 //        while(t=zeng(S,inf)) r+=t;  
160     }
161     return r;   
162 }
163 //pair<int,int> kk[4001];
164 //int cur;
165 int main()
166 {
167     std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y;
168     #ifdef LOCAL
169     freopen("111.in","r",stdin);
170     freopen("data.out","w",stdout);
171     #endif
172     cin>>n>>m;
173     S=0;T=m*n+1;
174     M(mp,0);M(head,0);
175 //    F(i,0,n-1)F(j,0,m-1){
176 //        int x,y;
177 //        cin>>x>>y;
178 //        mp[i][j]=x;
179 //        v[at(i,j)]=x;
180 //        in[at(i,j)]++;
181 //        if(j==m-1) in[at(i,j)]--;
182 //        if(j!=0) add(at(i,j),at(i,j-1),v[at(i-1,j)]);
183 //        if(y==0) continue;
184 ////        **********************************************
185 //        F(k,1,y){
186 //            int a,b;
187 //            cin>>a>>b;
188 //            kk[cur].first=at(i,j);
189 //            kk[cur].second=at(a,b);
190 //            cur++;
191 //            in[at(a,b)]++;
192 //            addedge(at(i,j),at(a,b),0);
193 ////            cout<<at(i,j)<<" "<<at(a,b)<<" &&&&&"<<endl;
194 //        }
195 //    }
196 //    F(i,1,m*n) cout<<in[i]<<" ";cout<<endl;    
197 //    cout<<"/*****************************"<<endl;
198 //    F(i,1,tot) cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<e[i].value<<endl;
199 //    cout<<"*****************************/"<<endl;
200     F(i,1,n*m){
201         int temp;
202         cin>>mp[i];
203         if(mp[i]>0) add(S,i,mp[i]);
204         else add(i,T,-mp[i]);
205         cin>>temp;
206         while(temp--){
207             int x,y;
208             cin>>x>>y;
209             add(x*m+y+1,i,inf);
210         }
211         if(i%m) add(i,i+1,inf);
212     }
213 //    topsort();
214 //    cout<<"))))))"<<endl;
215 //    F(i,1,m*n) if(in[i]==-1) cout<<i<<" ";cout<<"((((("<<endl;
216 //    M(e,0);M(head,-1);tot=0;
217     int q[4000];M(q,0);
218     int cur1=0,cur2=0;
219     for(int i=S;i<=T;++i){
220         if(!in[i]) q[cur2++]=i;
221         map[i]=-2;
222     } 
223     int sum=0; 
224     while(cur1<cur2){
225         int cnt=q[cur1++];map[cnt]=0;
226         if(mp[cnt]>0) sum+=mp[cnt];
227         for(int i=head[cnt];i;i=e[i].next)
228         {
229             if(i&1) if(!--in[e[i].to]) q[cur2++]=e[i].to;
230         }
231     }
232 //    F(i,1,m*n) cout<<in[i]<<" ";cout<<endl;    
233 //    cout<<"v: "<<endl;
234 //    F(i,1,m*n) cout<<v[i]<<" ";cout<<endl;
235 //    F(i,0,n-1)F(j,0,m-1){
236 //        if(in[at(i,j)]==-1) continue;
237 ////        cout<<at(i,j)<<" : "<<in[at(i,j)]<<"@ "<<endl;
238 //        if(j!=0&&in[at(i,j-1)]!=-1) add(at(i,j-1),at(i,j),inf);
239 //        if(v[at(i,j)]==0) continue;
240 //        if(v[at(i,j)]>0) add(31,at(i,j),v[at(i,j)]),sum+=v[at(i,j)];
241 //        else add(at(i,j),32,-v[at(i,j)]);
242 //    }
243 //    while(cur!=0){
244 //        cur--;
245 //        if(in[kk[cur].first]==-1||in[kk[cur].second]==-1) continue;
246 //        int u=kk[cur].first;
247 //        int v=kk[cur].second;
248 //        add(v,u,inf);
249 //    }
250 //    cout<<"/*****************************"<<endl;
251 //    F(i,1,tot) cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<e[i].value<<endl;
252 //    cout<<"*****************************/"<<endl;
253 //    cout<<sum<<endl;
254     cout<<sum-dinic()<<endl;
255     return 0;
256 }
257 /*
258 3 2
259 10 0
260 20 0
261 -10 0
262 -5 1 0 0
263 100 1 2 1
264 100 0
265 */
植物大战僵尸

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值