经过长时间的旅行,很长时间没写过博客了,这次把上次WA的题目过了。
由于每次蜥蜴从石柱上跳下时,石柱的高度会-1,可以看做占了一格的流量。
建图:
1.建超级源和超级汇,设超级源连到每只蜥蜴的边容量为1,每个可以跳到外面的点连到超级汇的边的容量为maxlongint。
2.对于每个点建一个虚点,连边到此虚点,边容量为该点石柱高度。对于每个可以互相跳到的点,建立容量为maxlongint的边。这样当前点到其他点的总容量为该点的石柱高度。(拆点)
然后跑一遍Dinic就好了。
注意用蜥蜴的总数减去最大流才是答案。
code:
/************************************************************** Problem: 1066 User: yekehe Language: C++ Result: Accepted Time:40 ms Memory:6380 kb ****************************************************************/ #include <cstdio> #include <string> #include <cstring> #include <iostream> using namespace std; int r,c,d,a[25][25],L; string S; int head[1000],nxt[100000],W[100000],To[100000],cnt; void add(int x,int y,int c) { W[cnt]=c; To[cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; cnt++; } int check(int x,int y,int fx,int fy) { return (x-fx)*(x-fx)+(y-fy)*(y-fy)<=d*d; } int l[1000000],dist[1000]; int BFS() { int tl=0,hd=0; hd=tl=0; l[++tl]=0; memset(dist,-1,sizeof dist); dist[0]=1; while(hd<tl){ int front=l[++hd]; for(int i=head[front];i!=-1;i=nxt[i]){ if(dist[To[i]]==-1 && W[i]){ dist[To[i]]=dist[front]+1; l[++tl]=To[i]; } } } return dist[r*c*2+1]!=-1; } int DFS(int now,int x) { if(now==r*c*2+1 || !x)return x; int res=0; for(int i=head[now];i!=-1 && x;i=nxt[i]){ if(dist[now]+1==dist[To[i]]&&W[i]){ int DK=DFS(To[i],min(x,W[i])); W[i]-=DK;W[i^1]+=DK; x-=DK;res+=DK; } } if(!res)dist[now]=-1; return res; } void Dinic() { int ans=0; while(BFS()) ans+=DFS(0,2e9); printf("%d",L-ans); return ; } int main() { // freopen("x.txt","r",stdin); scanf("%d%d%d",&r,&c,&d); memset(nxt,-1,sizeof nxt); memset(head,-1,sizeof head); register int i,j,k,h; #define Size ( r*c ) #define fr ( (i-1)*c+j ) #define to ( (k-1)*c+h ) for(i=1;i<=r;i++){ cin>>S; for(j=0;j<S.size();j++){ a[i][j+1]=S[j]-'0'; } } for(i=1;i<=r;i++){ cin>>S; for(j=1;j<=S.size();j++){ if(S[j-1]=='L'){ L++;//求蜥蜴总数 add(0,fr,1); add(fr,0,0); } } } for(i=1;i<=r;i++) for(j=1;j<=c;j++){ if(!a[i][j])continue; add(fr,fr+Size,a[i][j]); add(fr+Size,fr,0); for(k=1;k<=r;k++) for(h=1;h<=c;h++){ if(i==k&&j==h)continue; if(a[k][h]/*减少边的总量*/&&check(i,j,k,h)){ add(fr+Size,to,2e9); add(to,fr+Size,0); } } } for(i=1;i<=r;i++) for(j=1;j<=c;j++){ if(i<=d || j<=d || r-i+1<=d || c-j+1<=d){ if(!a[i][j])continue;//减少边的总量 add(fr+Size,Size<<1|1,2e9); add(Size<<1|1,fr+Size,0); } } Dinic(); return 0; }