您的位置:首页 > 其它

hdu 3046 Pleasant sheep and big big wolf(sap最大流)

2013-08-02 22:20 417 查看
开始在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));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: