[2019.1.17]BZOJ1066 [SCOI2007]蜥蜴
阿新 • • 發佈:2019-03-17
高度 最大流 如何 bit sca pan sizeof getc +=
首先,發現數據範圍很小,結合題意認為這是一道搜索網絡流題。
考慮建模。
我們把圖中高度不為0的石柱看做點,如何連邊呢?
首先,兩個相互可以到達的石柱之間需要連容量為\(inf\)的邊,因為如果石柱不消失,蜥蜴可以在這兩個石柱之間條無數次。
然後建立匯點\(t\),每一個與邊界距離不超過\(d\)的點都向\(t\)連一條容量為\(inf\)的邊,因為任何一根可以跳出邊界的石柱在不消失的情況下,都可以讓無數只蜥蜴跳出。
接下來建立源點\(s\),\(s\)向每一個有蜥蜴的石柱連一條容量為1的邊。這個很好理解,因為每個石柱上只有1只蜥蜴,所以這條邊只能流過1的流量。
剩下的是最重要的,如何保證一個石柱只被踩它的高度次呢?
我們拆點,將一個石柱拆成兩個點,一個連著所有入邊,一個連著所有出邊,入邊點向出邊點連容量為石柱高度的邊。
然後這個網絡的最大流就是答案。
註意要輸出的是不能跳出邊界的蜥蜴數量,所以我們要用蜥蜴總數減去答案輸出。
code:
#include<bits/stdc++.h> #define REV(x) ((x&1)?x+1:x-1) using namespace std; const int INF=1e9; struct edge{ int t,w,nxt; }e[100010]; struct node{ int x,y; }d[810]; int n,m,dn,mp[25][25],t,r,cnt,be[810],dep[810],vis[810],tl,ans; char tc; queue<int>q; void getn(int &x){ x=getchar(); while(!isdigit(x))x=getchar(); x-='0'; } void getc(char &x){ x=getchar(); while(x!='.'&&x!='L')x=getchar(); } bool P(int xf,int yf,int xt,int yt){ return (xf-xt)*(xf-xt)+(yf-yt)*(yf-yt)<=r*r; } void add(int x,int y,int v){ e[++cnt].t=y,e[cnt].w=v,e[cnt].nxt=be[x],be[x]=cnt; } void Add(int x,int y,int v){ add(x,y,v),add(y,x,0); } void Build(){ for(int i=1;i<=dn;i+=2)for(int j=i+2;j<=dn;j+=2)P(d[i].x,d[i].y,d[j].x,d[j].y)?Add(i+1,j,INF),Add(j+1,i,INF),0:0; for(int i=1;i<=dn;i+=2)(min(d[i].x,n-d[i].x+1)<=r||min(d[i].y,m-d[i].y+1)<=r)?Add(i+1,dn+1,INF),0:0; } bool Getd(){ memset(dep,0,sizeof(dep)); int tt=0; q.push(0),dep[0]=1; while(!q.empty()){ t=q.front(),q.pop(),tt++; for(int i=be[t];i;i=e[i].nxt)(!dep[e[i].t]&&e[i].w)?dep[e[i].t]=dep[t]+1,q.push(e[i].t),0:0; } return dep[dn+1]; } int dfs(int x,int nf){ if(x==dn+1)return nf; vis[x]=1; int tf,af=0; for(int i=be[x];nf&&i;i=e[i].nxt)(!vis[e[i].t]&&e[i].w&&dep[e[i].t]==dep[x]+1)?tf=dfs(e[i].t,min(nf,e[i].w)),e[i].w-=tf,e[REV(i)].w+=tf,nf-=tf,af+=tf:0; return vis[x]=0,af; } void Dinic(){ while(Getd())ans+=dfs(0,INF); } int main(){ scanf("%d%d%d",&n,&m,&r); for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)getn(t),t?mp[i][j]=++dn,d[dn]=(node){i,j},Add(dn,dn+1,t),++dn:0; for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)getc(tc),tc=='L'?(++tl,mp[i][j]?Add(0,mp[i][j],1),0:0):0; Build(); Dinic(); printf("%d",tl-ans); return 0; }
[2019.1.17]BZOJ1066 [SCOI2007]蜥蜴