bzoj 1565 [NOI2009]植物大战僵尸 解题报告
1565: [NOI2009]植物大战僵尸
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 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
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
————————————————我是分割线——————————————————————————
好题啊好题
这题折腾了三天,差点没吐出血来。
先拓扑排序求环,把环删掉。
之后重建图求最大权闭合子图,把一个植物向保护它的植物连边,跑一遍网络流即可。
第一次只过了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 */