题意:一群僵尸可以从边界进入。然后X是墙,D是需要保护的区域。问至少填多少围栏可以保护D里面。
思路:再在已有图的基础上添‘.‘
然后网络流枚举所有的点,如果是边界就连ED,INF.
如果是D就ST,INF。
其余上下左右相连1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>
#define me(x) memset(x,0,sizeof(x));
using namespace std;
#define INF 0x3f3f3f3f
#define mod 1000000009
const int MAXN = 33333;
const int MAXM = 33333;
//const int INF = 0x3f3f3f3f;
struct E
{
int TO, NEXT;
int CAP, FLOW;
}EDGE[MAXM], BED[MAXM], TEDGE[MAXM];
int TOL;
int HEAD[MAXN], CUR[MAXN], D[MAXN], THEAD[MAXM];
int P[MAXN], GAP[MAXN];
int NODE, ST, ED, BEGNUM;
void INIT(int A, int B,int C){
ST = A, ED = B, NODE = C;
BEGNUM = 0;
TOL = 0;
memset(HEAD, -1, sizeof(HEAD));
}
void ADDEDGE(int U, int V, int W, int RW = 0)
{
EDGE[TOL].TO = V; EDGE[TOL].CAP = W; EDGE[TOL].FLOW = 0;
EDGE[TOL].NEXT = HEAD[U]; HEAD[U] = TOL ++;
EDGE[TOL].TO = U; EDGE[TOL].CAP = RW; EDGE[TOL].FLOW = 0;
EDGE[TOL].NEXT = HEAD[V]; HEAD[V] = TOL ++;
}
void BFS(int S,int T)
{
memset(D, -1, sizeof(D));
memset(GAP, 0, sizeof(GAP));
queue<int> QUE;
GAP[0] = 1;
D[T] = 0;
QUE.push(T);
while (!QUE.empty()){
int U = QUE.front(); QUE.pop();
for (int i = HEAD[U]; i != -1;i = EDGE[i].NEXT){
int V = EDGE[i].TO;
if (D[V] == -1){
D[V] = D[U] + 1;
GAP[D[V]] ++;
QUE.push(V);
}
}
}
}
int STACK[MAXN];
int SAP(int S, int T, int N){
BFS(S, T);
if (D[S] == -1) return 0;
memcpy(CUR, HEAD, sizeof(HEAD));
int TOP = 0;
int U = S;
int ANS = 0;
while (D[S] < N){
if (U == T){
int MIN = INF;
int INSER;
for (int i = 0;i < TOP;i ++)
if (MIN > EDGE[STACK[i]].CAP - EDGE[STACK[i]].FLOW){
MIN = EDGE[STACK[i]].CAP - EDGE[STACK[i]].FLOW;
INSER = i;
}
for (int i = 0;i < TOP;i ++){
EDGE[STACK[i]].FLOW += MIN;
EDGE[STACK[i] ^ 1].FLOW -= MIN;
}
ANS += MIN;
TOP = INSER;
U = EDGE[STACK[TOP] ^ 1].TO;
continue;
}
bool FLAG = false;
int V;
for (int i = CUR[U];i != -1; i = EDGE[i].NEXT){
V = EDGE[i].TO;
if (EDGE[i].CAP - EDGE[i].FLOW > 0&& D[V] + 1 == D[U]){
FLAG = true;
CUR[U] = i;
break;
}
}
if (FLAG){
STACK[TOP ++] = CUR[U];
U = V;
continue;
}
int MIN = N;
for (int i = HEAD[U]; i != -1;i = EDGE[i].NEXT){
if (EDGE[i].CAP - EDGE[i].FLOW > 0&& D[EDGE[i].TO] < MIN){
MIN = D[EDGE[i].TO];
CUR[U] = i;
}
}
GAP[D[U]] --;
if (!GAP[D[U]]) return ANS;
D[U] = MIN + 1;
GAP[D[U]] ++;
if (U != S) U = EDGE[STACK[--TOP] ^ 1].TO;
}
return ANS;
}
E Q[MAXM];
int f[MAXN];
int n,m;
char mapp[200][200],a[200][200];
int main()
{
int t;
//while(scanf("%d", &t)!=EOF)
// {
// t=1;
scanf("%d", &t);
for (int cas = 1; cas <= t; ++cas)
{
scanf("%d%d",&n,&m);
INIT((n+2)*(m+2)+2,(n+2)*(m+2)+3,(n+2)*(m+2)+4);
for(int i=0;i<(n+2);i++)
for(int j=0;j<(m+2);j++)
mapp[i][j]='.';
// for(int i=0;i<n;i++)
// cin>>a[i];
for(int i=1;i<=(n);i++)
for(int j=1;j<=(m);j++)
cin>>mapp[i][j];
/* for(int i=0;i<=(n+1);i++)
{
for(int j=0;j<=(m+1);j++)
cout<<mapp[i][j];
cout<<endl;
}*/
for(int i=0;i<(n+2);i++)
for(int j=0;j<(m+2);j++)
{
if(mapp[i][j]=='X')
continue;
if(i==0||i==n+1||j==0||j==m+1)
ADDEDGE(i*(m+2)+j,ED,INF);
else
{
if(mapp[i+1][j]!='X')
ADDEDGE(i*(m+2)+j,(i+1)*(m+2)+j,1);
if(mapp[i-1][j]!='X')
ADDEDGE(i*(m+2)+j,(i-1)*(m+2)+j,1);
if(mapp[i][j+1]!='X')
ADDEDGE(i*(m+2)+j,i*(m+2)+j+1,1);
if(mapp[i][j-1]!='X')
ADDEDGE(i*(m+2)+j,i*(m+2)+j-1,1);
if(mapp[i][j]=='D')
ADDEDGE(ST,i*(m+2)+j,INF);
}
}
cout<<SAP(ST,ED,NODE)<<endl;
/* for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ADDEDGE(x,y,z);
}
// int cnt=SAP(1,n,n);
for (int x= HEAD[now]; x != -1; x = EDGE[x].NEXT)
{
int d=EDGE[x].TO;
if(EDGE[x].CAP - EDGE[x].FLOW>0&&!f[d])*/
// int val=0,ans;
// int T=TOL;
// cout<<cnt<<endl;
/* for(int i=0;i<TOL;i++)
Q[i]=EDGE[i];
ADDEDGE(i,j,INF);
ans=SAP(1,n,n);*/
}
// }
return 0;
}
437

被折叠的 条评论
为什么被折叠?



