zoukankan      html  css  js  c++  java
  • uva 11380 #拆点 最大流

    Problem D

    Down Went The Titanic

    Time Limit: 8 Second

    After the collision of the great Titanic with the iceberg, it went down. Now there are peoples floating in the cold water struggling with death. Some helping ship will arrive to save them. But they have to survive until the ships arrive. Now consider a water area with people, floating ices, large woods etc. Consider the following symbols:

     

    *          People staying on floating ice. People want to move from here as the floating ice cannot carry them for long time. Once a people move from here, the floating ice will get drowned. People can move to any of the four directions (north, east, west and south).

    ~          Water. People cannot go or move through them as water is extremely cold and not good enough for swimming.

    .           Floating ice. People can move to a floating ice. But floating ices are so light that they cannot float for long time, so people should move from here as soon as possible and once a people move from here, the floating ice will get drowned.

    @        Large iceberg. People can move here but cannot stay here as they are extremely cold. These icebergs will remain floating all the time. Note that, no two people can stay on floating ice or large iceberg at the same time.

    #          Large wood. This place is safe. People can move and stay here until the helping ships arrive. A large wood will get drowned if more than P people stay on it at the same time.

    Given the description of the area you have to find an optimal strategy that ensures the maximum number of living people.

    Input:

    The input contains a number of test cases. Each test case starts with a line containing three integers X, Y and P, where X, Y is the dimensions of the area (1 ≤ X, Y ≤ 30) and P (P ≤ 10) is the highest capacity of the large woods.  Next X lines each contains Y characters. These lines contain no blank spaces or any characters other than asterisk (*), tilde (~), dot (.), at (@) and hash (#). Not more than 50% of the total area has a people. Input will terminate with end of file (EOF). There is a blank line between two consecutive test cases.

    Output:

    For each test case print one line of output, an integer denoting the maximum number of survivors possible.

    SAMPLE INPUT

    OUTPUT FOR SAMPLE INPUT

    3 4 2

    *~~#

    ...@

    .~.*

    3 5 1

    ~~*~~

    #.@.#

    ~~*~~

    1 4 2

    **#~

    2

    2

    1

     

     

    Problemsetter: Ishtiak Zaman

    Special Thanks To: Md. Mahbubul Hasan

    自己YY了个直接枚举四周的方法,但WA了,现在还不知为啥要拆点。

    两份代码都记下:

    参考众神的AC:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<map>
    
    using namespace std;
    
    #define LL long long
    #define ULL unsigned long long
    #define UINT unsigned int
    #define MAX_INT 0x7fffffff
    #define MAX_LL 0x7fffffffffffffff
    #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
    #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
    #define cint const int
    #define INF 100000000
    #define MAXN 1810
    #define MAXM 10888
    #define MAXT 33
    
    struct edge{
        int u, v, cap, flow, nxt;
    }e[MAXM];
    int h[MAXN], cc;
    cint dx[]={-1, 1, 0, 0},
         dy[]={0, 0, -1, 1};
    
    char g[MAXT][MAXT];
    int X, Y;
    
    bool cango(int x, int y){
        if(x<0 || y<0 || x>=X || y>=Y) return false;
        return true;
    }
    
    void add(int u, int v, int cap){
        e[cc]=(edge){u, v, cap, 0, h[u]};
        h[u]=cc++;
        e[cc]=(edge){v, u, 0, 0, h[v]};
        h[v]=cc++;
    }
    
    int vis[MAXN], d[MAXN];
    bool bfs(cint s, cint t){
        queue<int> q;   q.push(s);
        memset(vis, 0, sizeof(vis));
        d[s]=0;     vis[s]=1;
        while(!q.empty()){
            int u=q.front();    q.pop();
            for(int i=h[u]; i!=-1; i=e[i].nxt){
                int v=e[i].v, cap=e[i].cap, ef=e[i].flow;
                if(!vis[v] && cap>ef){
                    d[v]=d[u]+1;
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
        return vis[t]==1;
    }
    
    int cur[MAXN];
    int dfs(int u, int a, cint &t){
        if(u==t || !a) return a;
        int f, flow=0;
        for(int &i=cur[u]; i!=-1; i=e[i].nxt){
            int v=e[i].v, cap=e[i].cap, ef=e[i].flow;
            if(d[v]==d[u]+1 && (f=dfs(v, MIN(a, cap-ef), t))>0){
                flow+=f;
                e[i].flow+=f;
                e[i^1].flow-=f;
                a-=f;
                if(!a) break;
            }
        }
        return flow;
    }
    
    int Dinic(cint s, cint t, cint n){
        int i, flow=0;
        while(bfs(s, t)){
            for(i=0; i<n; i++) cur[i]=h[i];
            flow+=dfs(s, INF, t);
        }
        return flow;
    }
    
    int Vin(int x, int y) { return x*Y+y+1; }
    int Vout(int x, int y) { return x*Y+y+1 + X*Y; }
    
    int main(){
        freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        int p;
        while(scanf(" %d %d %d", &X, &Y, &p)==3){   getchar();
            int i, k, j;
            for(i=0; i<X; i++) gets(g[i]);
    
            memset(h, -1, sizeof(h));   cc=0;
            for(i=0; i<X; i++)
                for(j=0; j<Y; j++){
                    char now=g[i][j];
                    if(now=='~') continue;          //水不可达
                    for(k=0; k<4; k++) if(cango(dx[k]+i, dy[k]+j)){     //四周
                        int nx=dx[k]+i, ny=dy[k]+j;
                        char nxt=g[nx][ny];
                        if(nxt=='~' || nxt=='*') continue;
                        add(Vout(i, j), Vin(nx, ny), INF);
                    }
    
                    if(now=='.') add(Vin(i, j), Vout(i, j), 1);
                    else if(now=='@') add(Vin(i, j), Vout(i, j), INF);
                    else if(now=='#'){
                        add(Vin(i, j), Vout(i, j), INF);                //注意INF
                        add(Vout(i, j), 2*X*Y+1, p);
                    }
                    else if(now=='*'){
                        add(0, Vin(i, j), 1);
                        add(Vin(i, j), Vout(i, j), 1);
                    }
                }
            printf("%d
    ", Dinic(0, 2*X*Y+1, 2*X*Y+2));
        }
        return 0;
    }
    

    YY的WA:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<map>
    
    using namespace std;
    
    #define LL long long
    #define ULL unsigned long long
    #define UINT unsigned int
    #define MAX_INT 0x7fffffff
    #define MAX_LL 0x7fffffffffffffff
    #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
    #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
    #define cint const int
    #define INF 100000000
    #define MAXN 1810
    #define MAXM 10888
    #define MAXT 33
    
    struct edge{
        int u, v, cap, flow, nxt;
    }e[MAXM];
    int h[MAXN], cc;
    cint dx[]={-1, 1, 0, 0},
         dy[]={0, 0, -1, 1};
    
    char g[MAXT][MAXT];
    int X, Y;
    
    bool cango(int x, int y){
        if(x<0 || y<0 || x>=X || y>=Y) return false;
        return true;
    }
    
    void add(int u, int v, int cap){
        e[cc]=(edge){u, v, cap, 0, h[u]};
        h[u]=cc++;
        e[cc]=(edge){v, u, 0, 0, h[v]};
        h[v]=cc++;
    }
    
    int vis[MAXN], d[MAXN];
    bool bfs(cint s, cint t){
        queue<int> q;   q.push(s);
        memset(vis, 0, sizeof(vis));
        d[s]=0;     vis[s]=1;
        while(!q.empty()){
            int u=q.front();    q.pop();
            for(int i=h[u]; i!=-1; i=e[i].nxt){
                int v=e[i].v, cap=e[i].cap, ef=e[i].flow;
                if(!vis[v] && cap>ef){
                    d[v]=d[u]+1;
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
        return vis[t]==1;
    }
    
    int cur[MAXN];
    int dfs(int u, int a, cint &t){
        if(u==t || !a) return a;
        int f, flow=0;
        for(int &i=cur[u]; i!=-1; i=e[i].nxt){
            int v=e[i].v, cap=e[i].cap, ef=e[i].flow;
            if(d[v]==d[u]+1 && (f=dfs(v, MIN(a, cap-ef), t)>0)){
                flow+=f;
                e[i].flow+=f;
                e[i^1].flow-=f;
                a-=f;
                if(!a) break;
            }
        }
        return flow;
    }
    
    int Dinic(cint s, cint t, cint n){
        int i, flow=0;
        while(bfs(s, t)){
            for(i=0; i<n; i++) cur[i]=h[i];
            flow+=dfs(s, INF, t);
        }
        return flow;
    }
    
    int id[MAXT][MAXT], cnt;
    int ID(int x, int y) { return id[x][y]>0 ? id[x][y] : id[x][y]=++cnt; }
    
    int main(){
    //    freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        int p;
        while(scanf(" %d %d %d", &X, &Y, &p)==3){   getchar();
            int i, k, j;
            for(i=0; i<X; i++) gets(g[i]);
    
            memset(h, -1, sizeof(h));   cc=0;
            memset(id, 0, sizeof(id));
            cnt=1;
            for(i=0; i<X; i++)
                for(j=0; j<Y; j++){
                    char now=g[i][j];
                    if(now=='~') continue;
                    if(now=='*') add(0, ID(i, j), 1);               //与源点相连
                    else if(now=='#') add(ID(i, j), 1, p);          //与汇点相连
                    int tcap=(now=='*'||now=='.' ? 1 : INF);        //出边限流,入边不限
                    for(k=0; k<4; k++) if(cango(dx[k]+i, dy[k]+j)){
                        int nx=dx[k]+i, ny=dy[k]+j;
                        char nxt=g[nx][ny];
                        if(nxt=='~' || nxt=='*') continue;
                        add(ID(i, j), ID(nx, ny), tcap);
                    }
                }
            printf("%d
    ", Dinic(0, 1, cnt+1));
        }
        return 0;
    }
    
  • 相关阅读:
    (转载)windows下安装配置Xampp
    (转载)C# winform 在一个窗体中如何设置另一个窗体的TextBox的值
    (转载)winform图片标尺控件
    (转载)WinformGDI+入门级实例——扫雷游戏(附源码)
    (转载)c# winform 窗体起始位置 设置
    (转载)C# GDI+ 画简单的图形:直线、矩形、扇形等
    (转载)C# ListView用法详解
    (转载)C#工具箱Menustrip控件中分割线的设置方法
    计算机中英文术语对照
    [JAVA]多线程之实现Callable接口
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3351166.html
Copyright © 2011-2022 走看看