思路:这题就是考建图、拆点建图、经典建模之一、自己YY的。。。。效果还不错
18 | 当两个傻瓜相遇 | 0MS | 432K | 3194B | G++ | 2014-04-25 20:18:02 |
代码记录一下:
#include<stdio.h> #include<string.h> #include<queue> #include<math.h> #include<algorithm> using namespace std; #define INF 0x7ffffff #define N 25 char map1[N][N]; char map2[N][N]; int path[1005][2]; int start,end; struct node { int to,next,cost; }edge[40005]; int head[1005]; int t_head[1005]; int hh[1005]; int level[1005]; int k; void init() { k=0; memset(head,-1,sizeof(head)); } void add(int x,int y,int val) { edge[k].to=y; edge[k].cost=val; edge[k].next=head[x]; head[x]=k++; edge[k].to=x; edge[k].cost=0; edge[k].next=head[y]; head[y]=k++; } int bfs(int s,int t)//对顶点进行标号、找出层次图 { memset(level,0,sizeof(level)); queue<int>q; q.push(s); level[s]=1; while(!q.empty()) { int now=q.front(); q.pop(); for(int i=head[now];i!=-1;i=edge[i].next) { int y=edge[i].to; if(!level[y]&&edge[i].cost>0) { level[y]=level[now]+1; q.push(y); } } } return level[t]!=0;//汇点是否在层次图中 } int dfs(int s,int cp)//在层次图中寻找增广路进行增广 { int flow=0,temp; int t; if(s==end||cp==0)return cp; for(;t_head[s]+1;t_head[s]=edge[t_head[s]].next) { int y=edge[t_head[s]].to; if(level[s]+1==level[y]) { temp=dfs(y,min(cp,edge[t_head[s]].cost)); if(temp>0) { edge[t_head[s]].cost-=temp; edge[t_head[s]^1].cost+=temp; flow+=temp; cp-=temp; if(cp==0)break; } } } return flow; } int dinic() { int ans=0,flow=0; while(bfs(start,end)) { for(int i=0;i<=end;i++) t_head[i]=head[i]; ans+=dfs(start,INF); } return ans; } int main() { int t,d,n; scanf("%d",&t); int cas=1; while(t--) { scanf("%d%d",&n,&d); init(); for(int i=1;i<=n;i++) scanf("%s",map1[i]+1); for(int i=1;i<=n;i++) scanf("%s",map2[i]+1); int len=strlen(map1[1]+1); int cnt=1; int w=1; for(int i=1;i<=n;i++) { for(int j=1;j<=len;j++) { if(map1[i][j]!='0') { if(map2[i][j]=='L') { hh[w++]=cnt; } path[cnt][0]=i; path[cnt][1]=j; add(cnt,cnt+1,map1[i][j]-'0'); cnt+=2; } } } for(int i=1;i<cnt;i+=2) { for(int j=1;j<cnt;j+=2) { if(i==j)continue; if((abs(path[i][0]-path[j][0])+abs(path[i][1]-path[j][1])<=d))//点与点之间是否可以连通 { add(i+1,j,INF); } } if((path[i][0]<=d)||((n-path[i][0])<d)||(path[i][1]<=d)||((len-path[i][1])<d)) { add(i+1,cnt,INF); } } for(int i=1;i<w;i++) { add(0,hh[i],1); } start=0;end=cnt; printf("Case #%d: ",cas++); int ans=dinic(); ans=w-ans-1; 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; }