BZOJ 1066 [SCOI2007]蜥蜴 (最大流)
题意:
一个方格图里$a_{ij}$为这个格子里柱子的高度,一些有高度的柱子上有一个蜥蜴,每个蜥蜴可以跳到距自己曼哈顿距离<=D的高度不为零的柱子上,同时当前柱子高度减1,蜥蜴的最终目的是跳出格子,问最终有多少蜥蜴跳不出去。
思路:
最大流,源点为S,汇点为T
对每个有高度的柱子拆点id→pid,容量为柱子高度 (id代表跳入,pid代表跳出)
对每个有蜥蜴的柱子,连接s→id,容量为1
对每根有高度的柱子a,以及与这根柱子曼哈顿距离小于D的所有柱子b,连接$pid_a \rightarrow id_b$,容量为inf
对每根有高度的柱子a,如果他到边界的曼哈顿距离小于D,那么他一定能跳出去,连接$pid_a \rightarrow t$,容量为inf
跑一哈,答案为numL-maxFlow
板子不太熟。。忘记了加边前要设置tot=1
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 2e6+100; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); int head[maxn],d[maxn];//层 int ver[maxm],edge[maxm],Next[maxm];//edge[i]: c for edge_i int n, m, s, t, tot, maxflow; queue<int>q; void add(int x, int y, int z){ //printf(" %d %d %d\n",x,y,z); ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot; ver[++tot]=x,edge[tot]=0,Next[tot]=head[y],head[y]=tot; } bool bfs(){ mem(d,0); while(!q.empty())q.pop(); q.push(s); d[s]=1; while(!q.empty()){ int x = q.front(); q.pop(); for(int i = head[x]; i; i = Next[i]){ if(edge[i] && !d[ver[i]]){ q.push(ver[i]); d[ver[i]] = d[x] + 1; if(ver[i] == t) return true; } } } return false; } int dinic(int x, int flow){ if(x==t) return flow; int rest = flow, k; for(int i = head[x]; i; i = Next[i]){ if(edge[i] && d[ver[i]] == d[x]+1){ k = dinic(ver[i], min(rest, edge[i])); if(!k) d[ver[i]] = 0; edge[i] -= k; edge[i^1] += k; rest -= k; } } return flow - rest; } char pm[30][30]; char xy[30][30]; int main(){ int r,c,D; scanf("%d %d %d", &r, &c, &D); getchar(); for(int i = 1; i <= r; i++){ scanf("%s", pm[i]); } for(int i = 1; i <= r; i++){ scanf("%s", xy[i]); } s = 0, t = 1001; tot =1; for(int i = 1; i <= r; i++){ for(int j = 0; j < c; j++){ int id = i*c+j; int pid = id + 500;//id -> pid //printf("1111: %d %d %d %d\n",i, j, id, pid); } } int num = 0; for(int i = 1; i <= r; i++){ for(int j = 0; j < c; j++){ int id = i*c+j; int pid = id + 500;//id -> pid //printf("1111: %d %d %d %d\n",i, j, id, pid); if(xy[i][j]=='L'){ add(s,id,1); num++; } if(pm[i][j]!='0'){ add(id,pid,pm[i][j]-'0'); } else continue; int hv = 0; for(int k = -D; k <= D; k++){ for(int p = -D; p <= D; p++){ if(abs(k)+abs(p)>D)continue; if(k==0 && p==0)continue; int dx = i+k; int dy = j+p; if((dx>r || dx < 1) || (dy >= c || dy < 0)){ if(hv)continue; add(pid, t, inf); hv=1; continue; } int iid = dx*c+dy; if(pm[dx][dy]=='0')continue; add(pid, iid, inf); } } } } int flow = 0; maxflow=0; while(bfs()){ while(1){ flow = dinic(s,inf); if(!flow)break; maxflow+=flow; } } printf("%d\n",num-maxflow); return 0; } /* 3 5 1 20000 03211 20000 ..... .LLL. ..... 3 3 1 200 031 200 ... .LL ... 3 3 0 200 031 200 L.. .L. ... */