zoukankan      html  css  js  c++  java
  • Vijos1653 疯狂的方格取数(MCMF)

    • 题意: 给出一个方格取数,最多能取k次,问最多能取到多少
    • 思路: 最大费用最大流
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<set>
    #include<cmath>
    #include<stack>
    #define ll long long
    using namespace std;
    typedef  pair<int,int> pii;
    
    const int N = 1e5+10;
    const int INF = 0x3f3f3f3f;
    
    
    struct E{
        int u,v,flow,nxt,w;
        E(){}
        E(int u,int v,int flow,int nxt,int w):u(u),v(v),flow(flow),nxt(nxt),w(w){}
    }e[N*2];
    
    int n,m,k,sp,tp,tot;
    int head[N],dis[N],pre[N],cur[N],vis[N];
    ll cost;
    void init(){
        tot = 0;    memset(head,-1,sizeof head);
    }
    void addE(int u,int v,int flow,int cost){
        e[tot].u = u; e[tot].v = v; e[tot].flow = flow; e[tot].nxt = head[u]; e[tot].w = cost; head[u] = tot++;
        e[tot].u = v; e[tot].v = u; e[tot].flow = 0; e[tot].nxt = head[v]; e[tot].w = -cost; head[v] = tot++;
    }
    int q[N];
    int bfs(){
        int qtop = 0,qend=0;
        memset(vis,0,sizeof vis);
        memset(dis,0x3f,sizeof dis);  
        dis[sp] = 0;    
        q[qend++] = sp;
        while(qtop!=qend){
            int u = q[qtop++];
            vis[u] = 0;
            // if(u==tp)   return true;
            for(int i=head[u];~i;i=e[i].nxt){
                int v = e[i].v;
                if(dis[v]>dis[u]+e[i].w && e[i].flow){
                    dis[v] = dis[u]+e[i].w;
                    if(!vis[v])  
                        q[qend++] = v,vis[v] = 1;
                }
            }
        }
        return dis[tp]!= INF;
    }
    int dfs(int u,int flow){
        int res = 0;
        if(u==tp)   return flow;
        vis[u] = 1;
        for(int i=head[u];i!=-1&&flow;i=e[i].nxt){
            int v = e[i].v;
            if(!vis[v] && dis[v]==dis[u]+e[i].w && e[i].flow){
                int d = dfs(v,min(e[i].flow,flow));
                e[i].flow -=d;
                e[i^1].flow += d;
                res+=d;
                flow -= d;
                cost += d*e[i].w;
            }
        }
        vis[u] = 0;
        if(!res)
            dis[u] = -2;
        return res;
    }
    int dinic(){
        int ans=0;
        while(bfs()){
            ans+=dfs(sp,INF);
        }
        return ans;
    }
    int main(){
        scanf("%d%d%d",&k,&m,&n);
        init();
        sp = n*m*2+1,tp = sp + 1;
        int cp,val,step = n*m;
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                scanf("%d",&val);
                cp = (i-1)*m + j;
                addE(cp,cp+step,1,-val);    // 流量为1,每个点只能被取一次
                addE(cp,cp+step,k,0);       // 流量为k,可以经过k次
                if(i<n){
                    addE(cp+step,(cp+m),k,0);   // 向下走
                }
                if(j<m){
                    addE(cp+step,(cp+1),k,0);   // 向右走
                }
            }
        }
        addE(sp,1,k,0);
        addE(n*m+step,tp,k,0);
        dinic();
        printf("%lld
    ",-cost); // 边权取反,求mcmf,最后答案取反
        return 0;
    }
    
    

    题目

  • 相关阅读:
    Parcel与Parcelable剖析
    Binder文集
    Charles 使用教程
    AsyncTask
    Android 编译时注解
    scanf(),gets(),getchar()
    银行家算法
    最长公共子序列(LCS)问题
    动态规划 求解数字三角形最大值
    参数 存在二维数组
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11617836.html
Copyright © 2011-2022 走看看