3
27
2016
0

[BZOJ1565] [NOI2009]植物大战僵尸

拓扑排序消圈+最大权闭合子图

因为每次僵尸都是从右往左走,那么我们对于右往左依次连边

然后每个点的攻击集合就是相当于选了攻击集合中的点就必须选择这个点。

那么我们反向建边,因为有可能出现循环保护的情况,所以先拓扑排序消圈然后按照最大权闭合子图的模型建网络流图即可。

bzoj 1565
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
 
int en,en1,n,m,ok[1005],cur[1005],h[1005],h1[1005],score[1005],du[1005],level[1005],S,T,now,mxval;
 
struct Edge{
int b,f,next,back;
}e[1000005],e1[1000005];
 
int Cal(int x,int y){return (x-1)*m+y;}
 
void AddEdge1(int sa,int sb){
e1[++en1].b=sb;
e1[en1].next=h1[sa];
h1[sa]=en1;
du[sb]++;
}
 
void AddEdge(int sa,int sb,int sc){
e[++en].b=sb;
e[en].back=en+1;
e[en].f=sc;
e[en].next=h[sa];
h[sa]=en;
swap(sa,sb);
e[++en].b=sb;
e[en].back=en-1;
e[en].f=0;
e[en].next=h[sa];
h[sa]=en;
}
 
int BFS(){
queue<int> Q;
Q.push(S);
memset(level,0,sizeof(level));
level[S]=1;
while(!Q.empty()){
    int u=Q.front();
    Q.pop();
    for(int i=h[u];i;i=e[i].next){
        int v=e[i].b;
        if(level[v] || !e[i].f)continue;
        Q.push(v);
        level[v]=level[u]+1;
    }
}
return level[T];
}
 
int DFS(int u,int flow){
if(u==T)return flow;
int f=flow;
for(int &i=cur[u];i;i=e[i].next){
    int v=e[i].b,fl;
    if(level[v]==level[u]+1 && e[i].f && (fl=DFS(v,min(f,e[i].f)))){
        f-=fl;
        e[i].f-=fl;
        e[e[i].back].f+=fl;
        if(!f)return flow;
    }
}
return flow-f;
}
 
int Dinic(){
int ans=0;
while(BFS()){
    for(int i=1;i<=T;i++)cur[i]=h[i];
    ans+=DFS(S,2100000000);
}
return ans;
}
 
void Toposort(){
queue<int> Q;
for(int i=1;i<=now;i++){
    if(!du[i]){ok[i]=1;Q.push(i);}
}
while(!Q.empty()){
    int u=Q.front();
    Q.pop();
    for(int i=h1[u];i;i=e1[i].next){
        int v=e1[i].b;
        du[v]--;
        if(!du[v]){ok[v]=1;Q.push(v);}
    }
}
}
 
int main(){
freopen("1565.in","r",stdin);
freopen("1565.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
        int can;
        now++;
        scanf("%d %d",&score[now],&can);
        for(int k=1;k<=can;k++){
            int dx,dy;
            scanf("%d %d",&dx,&dy);
            dx++;dy++;
            AddEdge1(now,Cal(dx,dy));
        }
        if(j!=m)AddEdge1(now+1,now);
    }
}
Toposort();
S=now+1;T=now+2;
for(int i=1;i<=now;i++){
    if(ok[i]){
        if(score[i]>=0){AddEdge(S,i,score[i]);mxval+=score[i];}
        else AddEdge(i,T,-score[i]);
        for(int j=h1[i];j;j=e1[j].next){
            int v=e1[j].b;
            if(ok[v])AddEdge(v,i,2100000000);
        }
    }
}
printf("%d\n",mxval-Dinic());
return 0;
}
Category: BZOJ | Tags: OI bzoj | Read Count: 526

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com