HDU 2732 Leapin' Lizards(最大流+拆点)

思路:这题就是考建图、拆点建图、经典建模之一、自己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;
}


你可能感兴趣的:(拆点建图)