zoukankan      html  css  js  c++  java
  • GYM101982E Cops And Roobers (网络流+拆点)

    题意

    给出一个n*m的矩阵,每个点有不同的花费,初始兔子在B点,你可以通过移除一些点,使得兔子无法到达边界,注意兔子只能上下左右移动。

    题解

    网络流,注意这种去掉点的套路,一定是拆点。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e6+100;
    const ll inf=1e15;
    
    int n,m,c;
    ll w[100];
    string S[100];
    int vis[100][100];
    int s,t;
    int sx,sy;
    int X[4]={1,0,-1,0};
    int Y[4]={0,1,0,-1};
    ll a[100][100];
    
    
    struct node {
        int u,v,nxt;
        ll w;
    }edge[maxn<<1];
    int head[maxn];
    int tot;
    void addedge (int u,int v,ll w) {
        edge[tot].u=u;
        edge[tot].v=v;
        edge[tot].w=w;
        edge[tot].nxt=head[u];
        head[u]=tot++;
        
        edge[tot].u=v;
        edge[tot].v=u;
        edge[tot].w=0;
        edge[tot].nxt=head[v];
        head[v]=tot++;
    }
    
    ll dep[maxn];
    ll inq[maxn];
    ll cur[maxn];
    ll wjm;
    ll maxflow=0;
    bool bfs () {
        for (int i=0;i<=t;i++) {
            cur[i]=head[i];
            dep[i]=inf;
            inq[i]=0;
        }
        dep[s]=0;
        queue<int> q;
        q.push(s);
        while (!q.empty()) {
            int u=q.front();
            q.pop();
            inq[u]=0;
            for (int i=head[u];i!=-1;i=edge[i].nxt) {
                int v=edge[i].v;
                if (dep[v]>dep[u]+1&&edge[i].w) {
                    dep[v]=dep[u]+1;
                    if (inq[v]==0) {
                        q.push(v);
                        inq[v]=1;
                    } 
                }
            }
        }
        if (dep[t]!=inf) return 1;
        return 0;
    }
    ll dfs (int u,ll flow) {
        ll increase=0;
        if (u==t) {
            wjm=1;
            maxflow+=flow;
            return flow;
        }
        ll used=0;
        for (int i=cur[u];i!=-1;i=edge[i].nxt) {
            cur[u]=i;
            int v=edge[i].v;
            if (edge[i].w&&dep[v]==dep[u]+1) {
                if (increase=dfs(v,min(flow-used,edge[i].w))) {
                    used+=increase;
                    edge[i].w-=increase;
                    edge[i^1].w+=increase;
                    if (used==flow) break;
                }
            }
        }
        return used;
    }
    ll Dinic () {
        maxflow=0;
        while (bfs()) {
            wjm=1;
            while (wjm==1) {
                wjm=0;
                dfs(s,inf);
            }
        }
        return maxflow;
    }
    
    
    int Bfs (int sx,int sy) {
        queue<pair<int,int> > q;
        q.push(make_pair(sx,sy));
        vis[sx][sy]=1;
        while (q.size()) {
            pair<int,int> tt=q.front();
            q.pop();
            for (int i=0;i<4;i++) {
                int tx=tt.first+X[i];
                int ty=tt.second+Y[i];
                if (tx<1||tx>n||ty<1||ty>m) {
                    return 0;
                }
                if (S[tx-1][ty-1]>='a'&&S[tx-1][ty-1]<='z') continue;
                if (!vis[tx][ty]) {
                    q.push(make_pair(tx,ty));
                    vis[tx][ty]=1;
                }
            }
        }
        return 1;
    }
    
    
    
    
    
    int main () {
        scanf("%d%d%d",&m,&n,&c);
        memset(head,-1,sizeof(head));
        for (int i=0;i<n;i++) cin>>S[i];
        for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (S[i-1][j-1]=='B') sx=i,sy=j;
        
        //1~n*m为每个点的上点
        //n*m+1~n*m*2为每个点的下点
        //n*m*2+1为汇点
        s=0;
        t=n*m*2+1;
        for (int i=0;i<c;i++) scanf("%lld",w+i);
        for (int i=1;i<=n;i++) {
            for (int j=1;j<=m;j++) {
                if (S[i-1][j-1]>='a'&&S[i-1][j-1]<='z') 
                    a[i][j]=w[S[i-1][j-1]-'a'];
                else
                    a[i][j]=inf;
                //printf("%d ",a[i][j]);
            }
            //printf("
    ");
        }
        int ff=Bfs(sx,sy);
        if (!ff) {
            printf("-1
    ");
            return 0;
        }
        addedge(s,(sx-1)*m+sy,inf);
        for (int i=1;i<=n;i++) {
            for (int j=1;j<=m;j++) {
                addedge((i-1)*m+j,(i-1)*m+j+n*m,a[i][j]);
                for (int k=0;k<4;k++) {
                    int tx=i+X[k];
                    int ty=j+Y[k];
                    if (tx<1||tx>n||ty<1||ty>m) {
                        addedge((i-1)*m+j+n*m,t,inf);
                    }
                    else {
                        addedge((i-1)*m+j+n*m,(tx-1)*m+ty,inf);
                    }
                }
            }
        }
        printf("%lld
    ",Dinic());
    }
  • 相关阅读:
    [LeetCode]Valid Parentheses
    LeetCode & Q219-Contains Duplicate II
    LeetCode & Q217-Contains Duplicate-Easy
    LeetCode & Q189-Rotate Array-Easy
    LeetCode & Q169-Majority Element-Easy
    LeetCode & Q167-Two Sum II
    LeetCode & Q122-Best Time to Buy and Sell Stock II-Easy
    LeetCode & Q121-Best Time to Buy and Sell Stock-Easy
    MapReduce工作机制——Word Count实例(一)
    LeetCode & Q119-Pascal's Triangle II-Easy
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13940327.html
Copyright © 2011-2022 走看看