题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=2732
题目概述:
给出一张图,图上有一些柱子,同时有一些蜥蜴,给出蜥蜴一次能跳跃最多的格子数,蜥蜴的落脚点只能在柱子上,每根柱子有一定的耐久t,意味着在t只蜥蜴以这根柱子作为落脚点之后这根柱子就会崩塌,跳出地图的蜥蜴算作成功逃离,求最多逃离的蜥蜴数。
大致思路:
网络流还是不难看出的,考虑建图。
首先建一个超级源点,往每只蜥蜴连一条容量为1的边,然后遍历所有的柱子,在从柱子起跳能到达的所有柱子都连一条边,容量为当前柱子的耐久,同时对所有能跳出地图的柱子都连一条容量为柱子耐久的边到超级汇点。跑Dinic算法。
这个时候发现样例四中会有一个问题,耐久为3的那个点在上述建图过程中往其左边那两个2的点都连了一条容量为3的边,这时候最多可以有6只蜥蜴从耐久为3的柱子过去,这显然是不符合要求的。
那么如何解决呢?我们可以将一个点拆成一个入点和一个出点,从别的柱子连过来的都连到入点,从当前点连出去的都从出点连,在入点和出点之间连一条容量为当前柱子耐久的边,此时上述问题就可以得到很好地解决了。
(最后要注意d有可能等于4,数据范围不对)
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <vector> #include <ctime> #include <map> #include <stack> #include <set> #include <queue> #include <cstring> #include <algorithm> using namespace std; #define sacnf scanf #define scnaf scanf #define maxn 1010 #define maxm 35 #define inf 1061109567 #define Eps 0.000001 const double PI=acos(-1.0); #define mod 1000000007 #define MAXNUM 10000 void Swap(int &a,int &b) {int t=a;a=b;b=t;} int Abs(int x) {return (x<0)?-x:x;} typedef long long ll; struct Edge { int to,flow,nxt; } edges[maxn*maxn]; int cnt,n,m; int head[maxn],dep[maxn]; char num[maxn][maxn]; int dx[]={-1,0,1,0, -2,-1,0,1,2,1,0,-1, -3,-2,-1,0,1,2,3,2,1,0,-1,-2, -4,-3,-2,-1,0,1,2,3,4,3,2,1,0,-1,-2,-3}; int dy[]={0,1,0,-1, 0,1,2,1,0,-1,-2,-1, 0,1,2,3,2,1,0,-1,-2,-3,-2,-1, 0,1,2,3,4,3,2,1,0,-1,-2,-3,-4,-3,-2,-1}; void AddEdge(int from,int to,int flow) { cnt++;edges[cnt].to=to;edges[cnt].flow=flow; edges[cnt].nxt=head[from];head[from]=cnt; cnt++;edges[cnt].to=from;edges[cnt].flow=0; edges[cnt].nxt=head[to];head[to]=cnt; } int BFS(int s,int t) { queue<int> q; dep[s]=1;q.push(s); while(!q.empty()) { int u=q.front();q.pop(); for(int x=head[u];x!=0;x=edges[x].nxt) { if(dep[edges[x].to]==0&&edges[x].flow>0) { dep[edges[x].to]=dep[u]+1; q.push(edges[x].to); } } } return (dep[t]==0)?0:1; } int DFS(int now,int RouteMinFlow,int t) { int OldRouteMinFlow=0; if(RouteMinFlow<=0||now==t) return RouteMinFlow; for(int x=head[now];x!=0;x=edges[x].nxt) { if(dep[edges[x].to]==dep[now]+1) { int temp=DFS(edges[x].to,min(RouteMinFlow,edges[x].flow),t); edges[x+1].flow+=temp;edges[x].flow-=temp; RouteMinFlow-=temp;OldRouteMinFlow+=temp; if(RouteMinFlow==0) break; } } return OldRouteMinFlow; } int maxflow(int s,int t) { int ans=0; while(BFS(s,t)) { ans+=DFS(1,inf,t); memset(dep,0,sizeof(dep)); } return ans; } int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); //clock_t st=clock(); int T;scanf("%d",&T); for(int kase=1;kase<=T;kase++) { printf("Case #%d: ",kase); int d,total=0;n=4;m=maxn-1; scanf("%d%d",&n,&d);cnt=0; memset(head,0,sizeof(head)); memset(dep,0,sizeof(dep)); memset(num,0,sizeof(num));getchar(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%c",&num[i][j]); if(num[i][j]==' ') {m=j;break;} if(num[i][j]!='0') { int t=(i-1)*(m-1)+j; AddEdge(t*2,t*2+1,num[i][j]-'0'); } } } char c;d=(d==1)?4:((d==2)?12:((d==3)?24:40)); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%c",&c); if(c=='L') { int t=(i-1)*(m-1)+j; AddEdge(1,t*2,1);total++; } } }m--; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(num[i][j]=='0') continue; int temp=0; for(int k=0;k<d;k++) { int nx=i+dx[k]; int ny=j+dy[k]; if(nx>0&&nx<=n&&ny>0&&ny<=m) { if(num[nx][ny]!='0') { AddEdge(((i-1)*m+j)*2+1,((nx-1)*m+ny)*2,num[i][j]-'0'); } } else temp++; } if(temp!=0) { AddEdge(((i-1)*m+j)*2+1,n*m*2+2,num[i][j]-'0'); } } } int ans=maxflow(1,n*m*2+2);total-=ans; if(total==0) printf("no lizard was"); else if(total==1) printf("1 lizard was"); else printf("%d lizards were",total); printf(" left behind. "); } //clock_t ed=clock(); //printf(" Time Used : %.5lf Ms. ",(double)(ed-st)/CLOCKS_PER_SEC); return 0; }