zoukankan      html  css  js  c++  java
  • 【网络流24题】负载平衡问题

    这又是一道我没有当场想出来的题

    题面

    https://www.luogu.org/problemnew/show/P4016

    题解

    $S$连初始状态,末状态连$T$,转移边流量为$INF$,费用为$1$。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<queue>
    #define N 105
    #define INF 1000000007
    #define T (n+1)
    #define S 0
    #define LL long long
    #define ri register int
    using namespace std;
    
    int n,a[N];
    
    struct graph {
      vector<int> to,w,c;
      vector<int> ed[N];
      LL dis[N]; int cur[N];
      bool vis[N];
      void add_edge(int a,int b,int aw,int ac) {
        to.push_back(b); w.push_back(aw); c.push_back(ac);  ed[a].push_back(to.size()-1);
        to.push_back(a); w.push_back(0);  c.push_back(-ac); ed[b].push_back(to.size()-1);
      }
      bool spfa() {
        memset(dis,0x2f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        queue<int> q;
        dis[S]=0;q.push(S);vis[S]=1;
        while (!q.empty()) {
          int x=q.front(); q.pop();
          for (ri i=0;i<ed[x].size();i++) {
            int e=ed[x][i];
            if (dis[to[e]]>dis[x]+c[e] && w[e]) {
              dis[to[e]]=dis[x]+c[e];
              if (!vis[to[e]]) vis[to[e]]=1,q.push(to[e]);
            }
          }
          vis[x]=0;
        }
        return dis[T]<INF;
      }
      int dfs(int x,int lim) {
        if (x==T || !lim) return lim;
        LL sum=0; vis[x]=1;
        for (ri &i=cur[x];i<ed[x].size();i++) {
          int e=ed[x][i];
          if (dis[x]+c[e]==dis[to[e]] && w[e] && !vis[to[e]]) {
            int f=dfs(to[e],min(lim,w[e]));
            w[e]-=f; w[1^e]+=f;
            lim-=f; sum+=f;
            if (!lim) return sum;
          }
        }
        return sum;
      }
      LL zkw() {
        LL ret=0;
        while (spfa()) {
          memset(vis,0,sizeof(vis));
          memset(cur,0,sizeof(cur));
          ret+=dfs(S,INF)*dis[T];
        }
        return ret;
      }
    } G;
    
    
    int suc(int x) {
      x++;
      if (x==n+1) return 1; else return x;
    }
    int pre(int x) {
      x--;
      if (x==0) return n; else return x;
    }
    
    int main() {
      scanf("%d",&n);
      int sum=0;
      for (ri i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i];
      int av=sum/n;
      for (ri i=1;i<=n;i++) {
        G.add_edge(S,i,a[i],0);
        G.add_edge(i,T,av,0);
        G.add_edge(i,suc(i),INF,1);
        G.add_edge(i,pre(i),INF,1);
      }
      cout<<G.zkw()<<endl;
    }
  • 相关阅读:
    Win8系统 Python安装
    一些安卓开源框架整理
    Android 媒体键监听以及模拟媒体键盘的实现 demo
    android View 自动 GONE 问题
    Android 定时器TimerTask 简单使用
    关于Android studio 相对 eclipse 优点
    Java序列化与反序列化
    android shape的使用 边框
    Android Studio 修改 包名 package name
    Android WebView Long Press长按保存图片到手机
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11187930.html
Copyright © 2011-2022 走看看