【哈理工OJ 750题纪念!】Hrbust 2200 Escaping【建图+最大流-------Dinic】

Escaping
Time Limit: 1000 MSMemory Limit: 65536 K
Total Submit: 36(19 users)Total Accepted: 5(5 users)Rating: Special Judge: No
Description

One day, Large cruise ”Wu Kong” at sea. The station is represented by a square n*n divided into 1*1 blocks. Unfortunately , ” Wu Kong”  hit an iceberg .It will sink after t minutes ,then every people die. However, there will be some life-saving equipment in some rooms(not only one), People from one room to reach another adjacent room (only four) needs one minute .If the people on board to get these life-saving devices so that they will survive, find the greatest number of people can survive.

Input

The first line contains two integers n and t (2n10, 1t10). Each of the next n lines contains n integers(0<=A[i][j]<=9).the people number at this time. Each of the next n more lines contains n integers, Indicates that the room have the number of life-saving equipment(0<=B[i][j]<=9).

Output

Print a single number — the maximum number of people who will be saved.

Sample Input

3 3

1 0 0

1 0 0

1 0 0

0 0 0

0 0 0

0 0 3

Sample Output

2

Source
CPC23 2014-5
Author
Li jinmeng

题目大意:

现在有一艘船撞上了冰山,还有t秒所有人都会被淹死,船可以用一个n*n的图来表示,其中第一个输入的矩阵表示哪些地方有多少人,第二个输入的矩阵表示哪些地方有逃生的工具,只要人拿到了逃生工具就不会被淹死,问最多能够生存下来多少人。人每一秒都可以向周围四个方向移动一个格子。(上下左右)


思路:


1、很典型的多重匹配的模型,我比较喜欢跑最大牛,说以这里给出最大牛的做法。


2、建图:

①建立源点S,将其连入各个有人的点,其容量为各个点有的人数的个数。

②建立汇点T,将各个有逃生工具的点连入汇点T,其容量为各个点有的逃生工具的数量。

③对应将有人的地方和有逃生工具的地方做一个曼哈顿距离,其如果小于等于t,那么对应这个人就可以拿到这个工具。所以将这个有人的点连入有工具的点,容量设定为INF.


3、建好图之后直接跑最大流即可。这里最大流==多重匹配最大匹配数。


Ac代码:


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
    int from;
    int to;
    int w;
    int next;
}e[150*150*150];
int a[150][150];
int b[150][150];
int divv[150*150];
int cur[150*150];
int head[150*150];
int n,t,ss,tt,cont;
void add(int from,int to,int w)
{
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont++;
}
void Getmap()
{
    cont=0;
    ss=n*n*2+1;
    tt=ss+1;
    memset(head,-1,sizeof(head));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(a[i][j]>0)
            {
                add(ss,i*n+j+1,a[i][j]);
                add(i*n+j+1,ss,0);
            }
            if(b[i][j]>0)
            {
                add(n*n+i*n+j+1,tt,b[i][j]);
                add(tt,n*n+i*n+j+1,0);
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(a[i][j]>0)
            {
                for(int k=0;k<n;k++)
                {
                    for(int l=0;l<n;l++)
                    {
                        if(b[k][l]>0)
                        {
                            int u=i*n+j+1;
                            int v=n*n+k*n+l+1;
                            if(abs(i-k)+abs(j-l)<=t)
                            {
                                add(u,v,0x3f3f3f3f);
                                add(v,u,0);
                            }
                        }
                    }
                }
            }
        }
    }
}
int makedivv()
{
    memset(divv,0,sizeof(divv));
    divv[ss]=1;
    queue<int >s;
    s.push(ss);
    while(!s.empty())
    {
        int u=s.front();
        if(tt==u)return  1;
        s.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            int w=e[i].w;
            if(w&&divv[v]==0)
            {
                divv[v]=divv[u]+1;
                s.push(v);
            }
        }
    }
    return 0;
}
int Dfs(int u,int maxflow,int tt)
{
    if(u==tt)return maxflow;
    int ret=0;
    for(int &i=cur[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        int w=e[i].w;
        if(w&&divv[v]==divv[u]+1)
        {
            int f=Dfs(v,min(maxflow-ret,w),tt);
            e[i].w-=f;
            e[i^1].w+=f;
            ret+=f;
            if(ret==maxflow)return ret;
        }
    }
    return ret;
}
void Dinic()
{
    int ans=0;
    while(makedivv()==1)
    {
        memcpy(cur,head,sizeof(head));
        ans+=Dfs(ss,0x3f3f3f3f,tt);
    }
    printf("%d\n",ans);
}
int main()
{
    while(~scanf("%d%d",&n,&t))
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%d",&b[i][j]);
            }
        }
        Getmap();
        Dinic();
    }
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值