zoukankan      html  css  js  c++  java
  • [TJOI2015]线性规划

    题目洛谷P3973、BZOJ3996。

    题目大意:
    给你n,参数b[][]和c[](里面的数均>0),要你求一个数组A[](0/1,1表示选择),已知:
    1. 若同时选择X和Y,获得B[x][y]收益
    2. 若选择了X,需要C[x]的代价
    求最大的收益
    解题思路:
    我们将第一个条件转化为:若不同时选择X和Y,需要B[x][y]的代价。
    然后,建最小割模。
    将(i,j)看成一个点,从S向其连容量为B[i][j]+B[j][i](若i=j则只连B[i][j])。
    将每个i看成一个点,向T连容量为C[i]的边。
    然后因为选(i,j)必须要选i和j,所以从(i,j)分别向i和j连容量∞的边(i=j则只连一条)。
    求出最小割,然后答案就是sum(B)-最小割。

    C++ Code:

    #include<bits/stdc++.h>
    #define N 1005
    #define INF 0x3f3f3f3f
    int dis[N*N+N+5],iter[N*N+N+5],cnt=1,head[N*N+N+5],B[505][505],C[505],n,sm=0,level[N*N+N+5],q[7000005];
    bool vis[N*N+N+5];
    struct edge{
        int from,to,cap,nxt;
    }e[(N*N+N+5)<<2];
    inline int readint(){
        int c=getchar(),d=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
        return d;
    }
    inline void addedge(const int from,const int to,const int cap){
        e[++cnt]=(edge){from,to,cap,head[from]};
        head[from]=cnt;
        e[++cnt]=(edge){to,from,0,head[to]};
        head[to]=cnt;
    }
    void bfs(int s){
        memset(level,-1,sizeof(level));
        level[s]=0;
        int l=0,r=1;
        q[1]=s;
        while(l!=r){
            int u=q[l=l%7000000+1];
            for(int i=head[u];i!=-1;i=e[i].nxt){
                int v=e[i].to;
                if(level[v]<0&&e[i].cap>0){
                    level[v]=level[u]+1;
                    q[r=r%7000000+1]=v;
                }
            }
        }
    }
    int dfs(int u,int t,int f){
        if(u==t)return f;
        for(int& i=iter[u];i!=-1;i=e[i].nxt){
            int v=e[i].to;
            if(e[i].cap>0&&level[v]>level[u]){
                int d=dfs(v,t,std::min(f,e[i].cap));
                if(d){
                    e[i].cap-=d;
                    e[i^1].cap+=d;
                    return d;
                }else level[v]=-1;
            }
        }
        return 0;
    }
    int max_flow(int s,int t){
        int flow=0;
        while(1){
            bfs(s);
            if(level[t]<0)return flow;
            memcpy(iter,head,sizeof(iter));
            int f;
            while(f=dfs(s,t,INF))flow+=f;
        }
    }
    int main(){
    	n=readint();
    	memset(head,-1,sizeof head);
    	for(int i=1;i<=n;++i)
    	for(int j=1;j<=n;++j)sm+=(B[i][j]=readint());
    	for(int i=1;i<=n;++i)C[i]=readint();
    	for(int i=1;i<=n;++i)
    	for(int j=1;j<=n;++j){
    		int flow=(i==j)?B[i][i]:B[i][j]+B[j][i];
    		addedge(0,(i-1)*n+j,flow);
    		addedge((i-1)*n+j,n*n+i,INF);
    		if(i!=j)addedge((i-1)*n+j,n*n+j,INF);
    	}
    	for(int i=1;i<=n;++i)addedge(n*n+i,n*n+n+1,C[i]);
    	printf("%d
    ",sm-max_flow(0,n*n+n+1));
    }
    
  • 相关阅读:
    poj 3125 Printer Queue(STL注意事项)
    poj 2823 Sliding Window (STL超时版)
    poj 1088 滑雪 详解
    poj 2983 Is the Information Reliable?
    poj 2524 Ubiquitous Religions (STL与非STL的对比)
    高精度算法集合
    zTree v2.6 v3.0 初始化 / 方法对比
    下面是关于rownum的介绍(oracle)
    web性能优化
    jQueryEasyui,DataGrid几个常用的操作
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9105830.html
Copyright © 2011-2022 走看看