hdu2732 网络流经典建图

来源:互联网 发布:java游戏设计吃豆豆 编辑:程序博客网 时间:2024/05/16 20:47

http://acm.hdu.edu.cn/showproblem.php?pid=2732
题目大意:
给了n和d,表示有n行的图,(列数没给),对于每一个人都可以最长跳d的距离,对于每一个柱子有一个限定条件,只能从这里跳出去多少次。给了两张图,一张表示柱子的限定条件,一张给了现在那些柱子上有人。问有几个人不能跳到图的外面。
思路:
最大流建图。将图的外面抽象为一个汇点t,对于图中本来就可以跳出去的点,就可以连一条边到t了。对于可以跳到图中别的点的,就可以从这个点连一条边过去。比较直观的想法就是这些边的容量都设为这个柱子限定的次数,最后跑最大流就好了。但是如果这个柱子可以跳到旁边很多的点上,每一个边的容量都是这个限定次数的话,等于限定的次数被放大了。那么就考虑拆点,将每个点拆成点1,点2,1->2连一条边容量为限定的次数。对于能跳到别的边,就从2连一条边到外面的点,容量为INF。
步骤:
拆点
1.将能够直接跳出去的点,拆出的第一个点连到t,容量为限定的次数。
2.不能直接跳出去的,将点1连到点2,容量为限定的次数。
3.对于能跳到别的点的,将这个点2连到别的点的点1,容量为INF。
4.对于柱子上有人的,从s连一条边到该点的点1,容量为1。
跑最大流。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <stack>#include <vector>using namespace std;#define M 1009typedef struct edge{    int to,cap,rev;};vector<edge> G[M];char mp1[30][30],mp2[30][30];int level[M],iter[M];int n,m,d;int T;int s,t,sum;const int INF = 0x3f3f3f3f;void init(){    for(int i = 0;i <= 2*n*m+2;i++) G[i].clear();    sum = 0;}int to1(int i,int j){    return i*m + j+1;}int to2(int i,int j){    return to1(i,j) + n*m;}int dis(int x1,int x2,int y1,int y2){    return abs(x1-x2) + abs(y1-y2);}void add_edge(int u,int v,int cap){    G[u].push_back(edge{v,cap,G[v].size()});    G[v].push_back(edge{u,0,G[u].size()-1});}void bfs(int s){    memset(level,-1,sizeof(level));    level[s] = 0;    queue<int> q;    q.push(s);    while(!q.empty())    {        int v = q.front();        q.pop();        for(int i = 0;i < G[v].size();i++)        {            edge& e = G[v][i];            if(e.cap > 0 && level[e.to] < 0)            {                level[e.to] = level[v] + 1;                q.push(e.to);            }        }    }}int dfs(int u,int t,int f){    if(u == t) return f;    for(int& i = iter[u];i < G[u].size();i++)    {        edge& e = G[u][i];        if(e.cap > 0 && level[e.to] > level[u])        {            int d = dfs(e.to,t,min(f,e.cap));            if(d > 0)            {                e.cap -= d;                G[e.to][e.rev].cap += d;                return d;            }        }    }    return 0;}int max_flow(){    int flow = 0;    for(;;)    {        bfs(s);        memset(iter,0,sizeof(iter));        if(level[t] < 0) return flow;        int f = 0;        while((f = dfs(s,t,INF)) > 0) flow += f;    }}int main(){    scanf("%d",&T);    int k = 0;    while(k < T)    {        init();        k++;        scanf("%d %d",&n,&d);        for(int i = 0;i < n;i++) scanf("%s",mp1[i]);        m = strlen(mp1[0]);        for(int i = 0;i < n;i++) scanf("%s",mp2[i]);        s = 0;        t = 2*n*m+1;        for(int i = 0;i < n;i++)        {            for(int j = 0;j < m;j++)            {                if(mp1[i][j] - '0' > 0)                {                    //add_edge(to1(i,j),to2(i,j),mp1[i][j]-'0');                    if(i+1 <= d || j+1 <= d || n-i <= d || m-j <= d)                    {                        add_edge(to1(i,j),t,mp1[i][j]-'0');                        continue;                    }                    else add_edge(to1(i,j),to2(i,j),mp1[i][j]-'0');                    for(int ii = -d;ii <= d;ii++)                    {                        for(int jj = -d;jj <= d;jj++)                        {                            int x = i + ii;                            int y = j + jj;                            if(x == i && y == j) continue;                            if(x < 0 || y < 0 || x >= n || y >= m || dis(i,x,j,y) > d || mp1[x][y]-'0' == 0) continue;                            add_edge(to2(i,j),to1(x,y),INF);                        }                    }                }            }        }        for(int i = 0;i < n;i++)        {            for(int j = 0;j < m;j++)            {                if(mp2[i][j] == 'L')                {                    add_edge(s,to1(i,j),1);                    sum++;                }            }        }        int flow = max_flow();        int ans = sum - flow;        printf("Case #%d: ",k);        if(ans > 1) printf("%d lizards were left behind.\n",ans);        else if (ans == 1) printf("1 lizard was left behind.\n");        else if (ans == 0) printf("no lizard was left behind.\n");    }    return 0;}
0 0
原创粉丝点击