• 洛谷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;
    }
    

      

  • 相关阅读:
    Hashset;HashMap;ArrayList;
    排序方法(冒泡排序,直接选择排序,反转排序);
    父类引用指向子类的对象;
    SQL分支语句与循环语句
    ORCAL 数据库的约束以及SQL语言的四种类型
    Oracle基础数据类型与运算符
    集合
    数组的几种排序
    转换日期格式的工具类
    equals方法重写
  • 原文地址:https://www.cnblogs.com/guangheli/p/10367591.html
Copyright © 2020-2023  润新知