1. 程式人生 > >bzoj 1066(網絡流)

bzoj 1066(網絡流)

邊界 c++ -c closed blog spl def build img

題意

思路:網絡流分類裏面的題目。。所以自然要想網絡流啦。。。由題意可知:蜥蜴在高度>0的柱子上才有行動能力。。所以只要考慮高度大於0的柱子即可。.以圖的每根柱子作為點,對於柱子u,如果u能到達的柱子v,就連接(u , v).如果是邊有高度。。那麽選定一個起點s連接所有蜥蜴的起點,權值設為1。所有能跳出邊界的點連接終點t,權值設為inf。容量1代表這條邊被經過一次。這樣這個圖能跳出去的蜥蜴數量就是從s->t的最大流。但是這個圖是每個點有容量限制。這種我們可以把點拆成兩個。拆點之後得到的兩點,假如把u拆成兩個(u1,u2),那麽邊(u1 , u2)的容量就是u的容量,然後把原來頂點指出的邊變成出頂點指出,指向原來頂點的邊變成從入頂點指入。這道題裏面,先拆點,然後建圖。註意兩根不同柱子之間的容量要設為inf。然後跑一邊dinic就好了。

代碼:

技術分享
#include<bits/stdc++.h>
#define inf 0x3f3f3ff
using namespace std;
struct Node{int next ,  v , w;}e[500001];
int r , c  ,d , cnt , tot,mp[30][30] ,mark[30][30], head[802] ,lv[802] , it[802];
void ins(int u , int v , int w)
{e[tot].v = v , e[tot].w = w , e[tot].next = head[u] , head[u] = tot++;}
void
init() {tot=0,cnt = 0;memset(head,-1,sizeof(head));} void Insert(int u ,int v,int w) {ins(u,v,w);ins(v,u,0);} bool judge(int x1 , int y1,int x2 , int y2){ if(x1 <= 0 || y1 <= 0 || x2 <= 0 || y2 <= 0) return 0; if((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) <= d&&mp[x1][y1]&&mp[x2][y2]) return
1; return 0; } void build(){ for(int x1 = 1;x1 <= r;x1++) for(int y1 = 1; y1 <= c;y1++) for(int x2 = x1 - d;x2 <= x1 + d;x2++) for(int y2 = y1 - d;y2 <= y1 + d;y2++) if(judge(x1 , y1 , x2 , y2)) Insert(mark[x1][y1] + 400 , mark[x2][y2],inf); for(int x1 = 1; x1 <= r;x1++) for(int y1 = 1 ; y1 <= c;y1++) if(mp[x1][y1]) Insert(mark[x1][y1] ,mark[x1][y1] + 400 ,mp[x1][y1]); for(int x1 = 1; x1 <= r;x1++) for(int y1 = 1; y1 <= c;y1++) if(min(min(c-y1 + 1,y1) , min(x1 , r - x1 + 1))<= d) Insert(mark[x1][y1] + 400 , 801 , inf); } void bfs(int s){ memset(lv,-1,sizeof(lv)); queue<int>que; lv[s] = 0; que.push(s); while(!que.empty()){ int u = que.front(); que.pop(); for(int i = head[u];~i;i=e[i].next){ int v = e[i].v , w = e[i].w; if(w > 0 && lv[v] < 0) lv[v] = lv[u] + 1,que.push(v); } } } int dfs(int u ,int t , int f){ if(u==t) return f; int used = 0 , w; for(int i=head[u];~i;i=e[i].next){ int v = e[i].v; int w = e[i].w; if(lv[v] == lv[u]+1&&w > 0){ int d = dfs(v , t , min(f,w)); if(d > 0){ e[i].w -= f; e[i^1].w += f; return d; } } } return 0; } int max_flow(int s , int t){ int flow = 0; for(;;){ bfs(s); if(lv[t]<0) return flow; int f; while((f = dfs(s , t , inf))>0){ flow += f; } } return flow; } int main() { init(); scanf("%d%d%d",&r,&c,&d); char ch[30]; for(int i=1;i<=r;i++) for(int j = 1; j <= c;j++) mark[i][j] = ++cnt; int sum = 0; for(int i=1;i<=r;i++) { scanf("%s",ch+1); for(int j=1;j<=c;j++) mp[i][j] = ch[j] - 0; } for(int i = 1; i <= r;i++) { scanf("%s",ch+1); for(int j = 1; j <= c;j++) if(ch[j] == L) { sum++; Insert(0 , mark[i][j] , 1); } } build(); printf("%d\n",sum - max_flow(0 , 801)); }
View Code

bzoj 1066(網絡流)