网络流。。。。经典模型。。。HDU2732 && PKU 2711

http://acm.hdu.edu.cn/showproblem.php?pid=2732

题意:一个矩阵里有n*m个方格,有些方格中有l长的柱子,没相邻的两个柱子间的间距是1m,有些柱子上面有蜥蜴,现在你的目的是要使这些蜥蜴尽可能多的跳出到方格以为,假设蜥蜴每次能跳d远,但是它每离开一根柱子,柱子的高度就会降低1m,问最多能有多少只跳不出去。。。

一看题第一反应就是最大流,把每个有柱子的方格node拆点为node1,node2,两点之间权值为l,在d范围内的两个点连线,从一个点的node2连向另一点的node1,流量为Inf,然后建立源点s,汇点t 源点与有蜥蜴的点连起来,t会能够跳到外面的点连起来。

一开始一直wa。。。wa的郁闷之极。。。wa的好无语。。。一直找不到原因啊。。。。。后来实在没办法了。。。在sha崽大牛那里借了代码对拍。。我才发现,我犯了两个错误,表示强烈BS自己。。。

错误1 : 在输出结果的时候没有分清单复数,lizards 与lizard,然后改了 还是wa。。。郁闷之极。。。。。之后还是怀疑算法有误,然后继续拍代码,开始怀疑自己在建图的时候用double比较可能有精度的损失,然后造成误差。。但是怎么想都还是不会。。。于是放弃了这个怀疑,又还是怀疑sap的模板,这个模板我已经用了AC了很多题。。不可能会有错。。继续拍。。拍到最后才发现又是输出的错误。。

错误2:我还是把英语的单复数写错,在只有一个的时候 把was写成了were!!!

哎。。。这样的错误浪费了很多时间,贡献了。好几次wa。。。。表示BS自己。。。强烈无语。。。

代码:

#include<stdio.h> #include<string.h> #include<math.h> const int M = 40000 , Inf = 3 ; char map1[21][21],map2[21][21]; int n,d,l,s,t,m,k,en,dis[810],gap[810],cur[810],pre[810],flag[21][21]; struct Node { int vdx,flow,next,opp; }edge[M]; double dist(int x1,int y1,int x2,int y2) { return sqrt((double)((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))); } void add(int from,int to,int flow) { edge[en].vdx = to ; edge[en].flow = flow ; edge[en].opp = en+1 ; edge[en].next = edge[from].next ; edge[from].next = en ++ ; edge[en].vdx = from ; edge[en].flow = 0 ; edge[en].opp = en-1 ; edge[en].next = edge[to].next ; edge[to].next = en ++ ; } int checkmin(int aug,int flow) { if(aug==-1||aug>flow) return flow ; return aug ; } int sap() { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); for(int i=0;i<=t;i++) cur[i] = edge[i].next; int u = pre[s] = s,maxflow = 0,aug = -1; gap[0] = t; while(dis[s] < t) { loop: for(int &i = cur[u]; i != -1; i = edge[i].next) { int v = edge[i].vdx; if(edge[i].flow>0&& dis[u] == dis[v] + 1) { aug = checkmin(aug,edge[i].flow); pre[v] = u; u = v; if(v == t) { maxflow += aug; for(u = pre[u];v != s;v = u,u = pre[u]) { edge[cur[u]].flow -= aug; edge[edge[cur[u]].opp].flow += aug; } aug = -1; } goto loop; } } int mindis = t - 1; for(int i = edge[u].next; i != -1 ; i = edge[i].next) { int v = edge[i].vdx; if(edge[i].flow>0&& mindis>dis[v]) { cur[u] = i; mindis = dis[v]; } } if((--gap[dis[u]])== 0) break; gap[dis[u] = mindis+1] ++; u = pre[u]; } return maxflow; } int main() { int cas , T = 1 ; scanf("%d",&cas); while(cas--) { scanf("%d%d",&n,&d); for(int i=0;i<n;i++) scanf("%s",map1[i]); for(int i=0;i<n;i++) scanf("%s",map2[i]); l = strlen(map1[0]) ; k = 0 ; memset(flag,0,sizeof(flag)); for(int i=1;i<=n;i++) for(int j=1;j<=l;j++) if(map1[i-1][j-1]-'0'>0) flag[i][j] = ++k ; s=2*k+1,t=s+1,en=t+2; int from,to; for(int i=0;i<=t;i++) edge[i].next = -1 ; for(int i=1;i<=n;i++) { for(int j=1;j<=l;j++) { if(map1[i-1][j-1]-'0'>0) { from = flag[i][j] ; add(from,from+k,map1[i-1][j-1]-'0') ; for(int ii=1;ii<=n;ii++) { for(int jj=1;jj<=l;jj++) { if(ii==i&&jj==j) continue ; double dd = dist(i,j,ii,jj) ; if(flag[ii][jj]&&dd<=(double)d) { to = flag[ii][jj] ; add(from+k,to,Inf); } } } } } } int kk = 0 ; for(int i=0;i<n;i++) { for(int j=0;j<l;j++) { if(map2[i][j]=='L') { kk ++ ; from = flag[i+1][j+1] ; add(s,from,1) ; } } } for(int i=1;i<=n;i++) { for(int j=1;j<=l;j++) { if(map1[i-1][j-1]-'0'>0) { from = flag[i][j] ; if(i<=d||j<=d||n+1-i<=d||l+1-j<=d) { add(from+k,t,Inf); } } } } printf("Case #%d:",T++) ; int ans = kk-sap() ; if(ans==0) printf(" no lizard was left behind./n") ; else if(ans==1) printf(" 1 lizard was left behind./n"); else printf(" %d lizards were left behind./n",ans); } return 0 ; }

你可能感兴趣的:(算法,struct,网络,SAP,ini)