开始在hrbust上做的,数据改为20,用矩阵和普通的最大流算法均可以过!后来查的时候看到了hdu上的,数据比那个大很多,点数最多可达40000,第一次MLE,换成邻接表,第二次TLE,果断换算法,sap轻松秒过!
建图的方法就是远点连2, 终点连1,容量inf, 把每个挨着的格子连起来,容量1,求最小割! 这里求最小割很好理解,就像从一个2开始走,向1走,然后每次走都会经过一个格子的边界,不管有多少只wolf经过这个边界,只需要一个栅栏即可,也就是每个边界只有一个位置放栅栏,一般有三个或4个边界,这样,就能够建成一个从所有的2开始走向1的图,只要删除最小割上的点,就能阻止从1s和2s的连通!
下面是代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int MAXN=40010; const int MAXM=2000020; const int INF = 0x3fffffff; struct Node { int to,next,cap; }edge[MAXM];//注意是MAXM int tol, n, m; int head[MAXN]; int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN]; void addedge(int u,int v,int w,int rw=0) { edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++; edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];head[v]=tol++; } int sap(int start,int end,int nodenum) { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); memcpy(cur,head,sizeof(head)); int u=pre[start]=start,maxflow=0,aug=-1; gap[0]=nodenum; while(dis[start]<nodenum) { loop: for(int &i=cur[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap&&dis[u]==dis[v]+1) { if(aug==-1||aug>edge[i].cap) aug=edge[i].cap; pre[v]=u; u=v; if(v==end) { maxflow+=aug; for(u=pre[u];v!=start;v=u,u=pre[u]) { edge[cur[u]].cap-=aug; edge[cur[u]^1].cap+=aug; } aug=-1; } goto loop; } } int mindis=nodenum; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap&&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 o[205][205]; int main() { int icase = 1; while ( scanf("%d%d", &n, &m) != EOF ) { int S = 0, T = n*m+1; tol = 0; memset( head, -1, sizeof(head)); for ( int i = 1; i <= n; ++i ) for ( int j = 1; j <= m; ++j ) { scanf("%d", &o[i][j]); int u = (i-1)*m+j; if ( o[i][j] == 1 ) addedge( u, T, INF, 0 ); else if ( o[i][j] == 2 ) addedge( S, u, INF, 0 ); if ( i > 1 ) addedge( u, u-m, 1, 0 ); if ( i < n ) addedge( u, u+m, 1, 0 ); if ( j > 1 ) addedge( u, u-1, 1, 0 ); if ( j < m ) addedge( u, u+1, 1, 0 ); } printf("Case %d:\n%d\n", icase++, sap( S, T, T+1)); } }