zoukankan      html  css  js  c++  java
  • 洛谷P4013 数字梯形问题 费用流

    Code:

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn=10000;
    const int INF=100000+666;
    typedef long long ll;
    int A[700][700];
    int idx[700][700];
    int s,t,n,M,N;
    struct Edge{
    	int from,to,cap,cost;
    	Edge(int u,int v,int c,int f):from(u),to(v),cap(c),cost(f){}
    };
    struct MCMF{
    	vector<Edge>edges;
    	vector<int>G[maxn];
    	int d[maxn],inq[maxn],a[maxn],flow2[maxn];
    	queue<int>Q;
    	ll ans=0;
    	int flow=0;
    	void init(){
    	            for(int i=0;i<maxn;++i)G[i].clear();
    	            edges.clear();
    	            ans=0;
    	}
    	void addedge(int u,int v,int c,int f){
    		edges.push_back(Edge(u,v,c,f));    //正向弧
    		edges.push_back(Edge(v,u,0,-f));   //反向弧
    		int m=edges.size();
    		G[u].push_back(m-2);
    		G[v].push_back(m-1);
    	}
    	int SPFA(){
    		for(int i=0;i<=n;++i)d[i]=INF,flow2[i]=INF;
    		memset(inq,0,sizeof(inq));int f=INF;
    		d[s]=0,inq[s]=1;Q.push(s);
    		while(!Q.empty()){
    			int u=Q.front();Q.pop();inq[u]=0;
    			int sz=G[u].size();
    			for(int i=0;i<sz;++i){
    				  Edge e=edges[G[u][i]];
    				  if(e.cap>0&&d[e.to]>d[u]+e.cost){
    					  a[e.to]=G[u][i];
    					  d[e.to]=d[u]+e.cost;
    					  flow2[e.to]=min(flow2[u],e.cap);
    					  if(!inq[e.to]){inq[e.to]=1;Q.push(e.to);}
    				  }
    			}
    		}
    		if(d[t]==INF)return 0;
    		f=flow2[t];
    		flow+=f;
    		int u=edges[a[t]].from;
    		edges[a[t]].cap-=f;
    		edges[a[t]^1].cap+=f;
    		while(u!=s){
    			edges[a[u]].cap-=f;
    			edges[a[u]^1].cap+=f;
    			u=edges[a[u]].from;
    		}
    		ans+=(ll)(d[t]*f);
    		return 1;
    	}
    	ll getcost(){
    		while(SPFA());
    		return -ans;
    	}
    }op;
    void build(int cap_point,int cap_edge,int c2){
    	for(int i=1;i<=M;++i)op.addedge(s,idx[1][i],1,0);
    	for(int i=1;i<=N-1;++i)
    		for(int j=1;j<=M+i-1;++j)
    		{
    			op.addedge(idx[i][j],idx[i][j]+1,cap_point,-A[i][j]);
    			op.addedge(idx[i][j]+1,idx[i+1][j],cap_edge,0);
    			op.addedge(idx[i][j]+1,idx[i+1][j+1],cap_edge,0);
    		}
    	for(int i=1;i<=M+N-1;++i)op.addedge(idx[N][i],idx[N][i]+1,cap_point,-A[N][i]);
    	for(int i=1;i<=M+N-1;++i)op.addedge(idx[N][i]+1,t,c2,0);
    }
    int main()
    {
    	int cnt=1;
    	scanf("%d%d",&M,&N);
    	for(int i=1;i<=N;++i)
    		for(int j=1;j<=M+i-1;++j){
    			scanf("%d",&A[i][j]);
    			idx[i][j]=cnt,cnt+=2;
    		}
    	s=0,t=cnt,n=cnt;
                build(1,1,1);
                printf("%lld
    ",op.getcost());
                op.init();
                build(INF,1,INF);
                printf("%lld
    ",op.getcost());
                op.init();
                build(INF,INF,INF);
                printf("%lld",op.getcost());
                return 0;
    }
    

      

  • 相关阅读:
    Linux Shell编程入门
    vim 文件在linux不换行,只显示^M解决办法
    服务器高性能程序 磁盘I/O篇
    车牌识别_转自别人的博客
    ubuntu网络简单设置
    C++设计模式(转载)
    结构算法之道
    C++设计模式工厂方法
    二叉树的深度优先遍历、广度优先遍历和非递归遍历
    iptables
  • 原文地址:https://www.cnblogs.com/guangheli/p/10367591.html
Copyright © 2011-2022 走看看