• P4014 分配问题


    思路:费用流

    提交:(1)

    题解:

    源点向人连流量为(1)费用为(0)的边,人向每个工作连流量为(1)费用为(c_{i,j})的边,每个工作向汇点连流量为(1)费用为(0)的边。
    跑最小费用最大流。至于最大费用把费用全部取个负数输出答案时再取个负数就好。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    template<class I> inline I g(I& x) { x=0;
      register I f=1; register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
      do x=x*10+(ch-48); while(isdigit(ch=getchar())); return x*=f;
    } const int N=210,M=10010,Inf=0x3f3f3f3f;
    int n,m,s,t,ans,cnt=1,a[110][110];
    int vr[M<<1],nxt[M<<1],w[M<<1],c[M<<1],fir[N],d[N]; bool vis[N];
    inline void clear() {
      memset(nxt,0,sizeof(nxt)),memset(fir,0,sizeof(fir)); cnt=1; ans=0;
    }
    inline void add(int u,int v,int ww,int cc) {vr[++cnt]=v,nxt[cnt]=fir[u],w[cnt]=ww,c[cnt]=cc,fir[u]=cnt;}
    inline bool spfa() { memset(d,0x3f,sizeof(d)),memset(vis,0,sizeof(vis));
      queue<int> q; vis[s]=true,d[s]=0,q.push(s);
      while(!q.empty()) { R u=q.front(); q.pop(); vis[u]=false;
        for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
          if(w[i]&&d[v]>d[u]+c[i]) {
            d[v]=d[u]+c[i];
            if(!vis[v]) vis[v]=true,q.push(v);
          }
        }
      } return d[t]<Inf;
    }
    inline int dfs(int u,int f) {
      if(u==t||f<=0) return f; R res=f; vis[u]=true;
      for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(w[i]&&d[v]==d[u]+c[i]&&!vis[v]) {
          R tmp=dfs(v,min(res,w[i]));
          res-=tmp,w[i]-=tmp,w[i^1]+=tmp;
          if(!res) break;
        }
      } return f-res;
    }
    inline void dinic() {R tmp; while(spfa()) while(tmp=dfs(s,Inf),tmp!=0) memset(vis,0,sizeof(vis)),ans+=tmp*d[t];}
    inline void main() { g(n),s=2*n+1,t=2*n+2; 
      for(R i=1;i<=n;++i) for(R j=1,x;j<=n;++j) a[i][j]=g(x),add(i,j+n,1,x),add(j+n,i,0,-x);
      for(R i=1;i<=n;++i) add(s,i,1,0),add(i,s,0,0),add(i+n,t,1,0),add(t,i+n,0,0); dinic(); printf("%d
    ",ans); clear(); 
      for(R i=1;i<=n;++i) for(R j=1,x;j<=n;++j) x=a[i][j],add(i,j+n,1,-x),add(j+n,i,0,x);
      for(R i=1;i<=n;++i) add(s,i,1,0),add(i,s,0,0),add(i+n,t,1,0),add(t,i+n,0,0); dinic(); printf("%d
    ",-ans);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.08.19
    81

  • 相关阅读:
    Python 编码格式的使用
    解决cmd 运行python socket怎么终止运行
    解决win10子系统Ubuntu新装的mysql 不能root登陆方法
    浏览器中网址访问过程详解
    POJ 2502 最短路
    HDU 2859
    POJ 3186
    POJ 1661 暴力dp
    POJ 1015 陪审团问题
    CodeForces 1058E
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11376626.html
Copyright © 2020-2023  润新知