网络流板子/费用流板子 2018南京I题+2016青岛G题

2018南京I题:

dinic,链式前向星,数组队列,当前弧优化,不memset全部数组,抛弃满流点,bfs只找一条增广路,每次多路增广

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=2e3+10,maxm=2e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double PI=acos(-1.0);
//head
int casn,n,m,k;
class mxf{public:
  struct node{int to,next;ll cap;}e[maxm<<1];
  int cur[maxn],head[maxn],que[maxn],dis[maxn],nume=1,s,t;
  inline void adde(int a,int b,ll c){e[++nume]={b,head[a],c};head[a]=nume;}
  inline void add(int a,int b,ll c){adde(a,b,c);adde(b,a,0);}
  void init(int n=maxn-1){memset(head,0,(n+1)<<2);nume=1;}
  bool bfs(){
    memset(dis,-1,(t+1)<<2);
    dis[t]=0,que[0]=t;
    int tp=0,ed=1;
    while(tp!=ed){
      int now=que[tp++];tp%=maxn;
      for(int i=head[now];i;i=e[i].next){
				int to=e[i].to;
				if(dis[to]==-1&&e[i^1].cap){
					dis[to]=dis[now]+1;
					if(to==s) return true;
					que[ed++]=to;ed%=maxn;
				}
      }
    }
    return false;
  }
  ll dfs(int now,ll flow=0x3f3f3f3f){
    if(now==t||flow==0) return flow;
    ll use=0;
    for(int &i=head[now];i&&use!=flow;i=e[i].next){
        int to=e[i].to;
        if(dis[to]+1!=dis[now])continue;
        ll tmp=dfs(to,min(e[i].cap,flow-use));
        e[i].cap-=tmp,e[i^1].cap+=tmp,use+=tmp;
    }
    if(!use) dis[now]=-1;
    return use;
  }
  ll getflow(int ss,int tt){
  	s=ss,t=tt;ll ans=0;
    memcpy(cur,head,(t+1)<<2);
    while(bfs()){
      ans+=dfs(s);
			memcpy(head,cur,(t+1)<<2);
    }
    return ans;
  }
}net;
int main() {IO;
  cin>>n>>m>>k;
  int s=n+m+1,t=n+m+10,ss=n+m+2;
  net.init(t);net.add(s,ss,k);
  rep(i,1,n){
    net.add(s,i,1);net.add(ss,i,1);
    int x;cin>>x;
    while(x--){
			int y;cin>>y;
			net.add(i,n+y,1);
    }
  }
  while(m--) net.add(n+m+1,t,1);
  cout<<net.getflow(s,t);
	return 0;
}

2016青岛G

原始对偶算法+dijkstra正权化

#include <bits/stdc++.h>
#define endl ‘\n‘
#define ll long long
#pragma GCC optimize("Ofast")
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=2e3+10,maxm=2e6+10;
const double eps=1e-4;
int casn,n,m,k;
class mcf{public:
  #define tpp double
  struct node{int to;ll cap;tpp cost;int rev;};
  int prev[maxn],pree[maxn];
  tpp dis[maxn],cost,h[maxn];
  ll f;
  vector<node> g[maxn];
  void init(int n=maxn-2){rep(i,0,n+1) g[i].clear();}
  inline void add(int from,int to,ll cap,tpp cost){
    g[from].push_back({to,cap,cost,(int)g[to].size()});
    g[to].push_back({from,0,-cost,(int)g[from].size()});
  }
  tpp getcost(int s,int t){
    f=0,cost=0;
    fill(h,h+1+t,0);
    while(1){
        #define pdi pair<tpp,int>
        priority_queue<pdi,vector<pdi>,greater<pdi> >que;
        fill(dis,dis+t+1,1e10);
        dis[s]=0;que.push(make_pair(0,s));
        while(!que.empty()){
          auto now=que.top();que.pop();
          if(dis[now.second]<now.first)continue;
          int x=now.second;
          int cnt=0;
          for(auto &i:g[x])
            if(i.cap>0&&dis[i.to]>eps+dis[x]+h[x]-h[i.to]+i.cost){
              dis[i.to]=dis[x]+i.cost+h[x]-h[i.to];
              prev[i.to]=x;
              pree[i.to]=cnt++;
              que.push(make_pair(dis[i.to],i.to));
            }else cnt++;
        }
        if(dis[t]>=1e9)break;
        rep(i,0,t) h[i]+=dis[i];
        ll d=1e9;
        for(int now=t;now!=s;now=prev[now])
          d=min(d,g[prev[now]][pree[now]].cap);
        if(d==1e9)break;
        f+=d;cost+=d*h[t];
        for(int now=t;now!=s;now=prev[now]){
          node &e=g[prev[now]][pree[now]];
          e.cap-=d,g[now][e.rev].cap+=d;
        }
    }
    return cost;
  }
}net;
int a[maxn],b[maxn];
int main() {IO;
  cout<<fixed<<setprecision(2);
  cin>>casn;
  while(casn--){
    cin>>n>>m;
    int s=n+1,t=n+2;
    net.init(t);
    rep(i,1,n){
      cin>>a[i]>>b[i];
      int k=min(a[i],b[i]);
      a[i]-=k,b[i]-=k;
      if(a[i])net.add(s,i,a[i],0);
      if(b[i])net.add(i,t,b[i],0);
    }
    while(m--){
      int x,y,z;double p;
      cin>>x>>y>>z>>p;
      p=-log(1-p);
      if(z>0) net.add(x,y,1,0);
      if(z>1) net.add(x,y,z-1,p);
    }
    double ans=1.0-exp(-net.getcost(s,t));
    cout<<ans<<endl;
  }
	return 0;
}

EK+spfa

#include <bits/stdc++.h>
#define endl ‘\n‘
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e3+10,maxm=1e5+10;
const double eps=1e-8;
int casn,n,m,k;
class mcf{public:
  #define tpp double
  int nume=1,s,t,mflow;
  int head[maxn],flow[maxn],pre[maxn];
  tpp dis[maxn],mcost;
  struct node{int to,next,cap;tpp cost;}e[maxm<<1];
  void init(int n=maxn-10){
    fill(head,head+n+2,0);
    nume=1,mflow=mcost=0;
  }
  inline void add(int from,int to,int cap,tpp cost){
      e[++nume]={to,head[from],cap,cost};head[from]=nume;
      e[++nume]={from,head[to],0,-cost};head[to]=nume;
  }
  bool vis[maxn];
  queue<int>q;
  bool spfa(){
      fill(dis,dis+2+t,1e9);
      fill(vis,vis+2+t,false);
      dis[s]=0;flow[s]=1e9;q.push(s);
      while (!q.empty()){
          int now=q.front();q.pop();
          vis[now]=false;
          for (int i=head[now];i;i=e[i].next){
              int to=e[i].to;
              tpp cost=e[i].cost;
              if (e[i].cap&&dis[now]+cost+eps<dis[to]){
                  dis[to]=dis[now]+cost;
                  flow[to]=min(flow[now],e[i].cap);
                  pre[to]=i;
                  if (!vis[to]){
                      vis[to]=true;
                      q.push(to);
                  }
              }
          }
      }
      return dis[t]<1e9;
  }
  void update(){
      int x=t;
      while (x!=s){
          int i=pre[x];
          e[i].cap-=flow[t];
          e[i^1].cap+=flow[t];
          x=e[i^1].to;
      }
      mflow+=flow[t];
      mcost+=(tpp)flow[t]*dis[t];
  }
  double getcost(int s,int t){
      this->s=s;this->t=t;
      while (spfa())update();
      return mcost;
  }
}net;
int a[maxn],b[maxn];
int main() {IO;
  cout<<fixed<<setprecision(2);
  while(cin>>casn){
    while(casn--){
      cin>>n>>m;
      int s=n+1,t=n+2;
      net.init(t);
      rep(i,1,n){
        cin>>a[i]>>b[i];
        int k=min(a[i],b[i]);
        a[i]-=k,b[i]-=k;
        if(a[i])net.add(s,i,a[i],0);
        if(b[i])net.add(i,t,b[i],0);
      }
      while(m--){
        int x,y,z;double p;
        cin>>x>>y>>z>>p;
        p=-log(1-p);
        if(z>0) net.add(x,y,1,0);
        if(z>1) net.add(x,y,z-1,p);
      }
      double ans=net.getcost(s,t);
      ans=exp(-ans);
      ans=1.0-ans;
      cout<<ans<<endl;
    }
  }
	return 0;
}

原文地址:https://www.cnblogs.com/nervendnig/p/10777628.html

时间: 2024-08-30 13:23:09

网络流板子/费用流板子 2018南京I题+2016青岛G题的相关文章

NEU 1458 方格取数(网络流之费用流)

题目地址:NEU 1458 跟杭电上的那两个方格取数不太一样..这个可以重复,但是取和的时候只能加一次.建图思路基本一会就出来.同样的拆点,只不过这题需要再拆个边,其中一条费用0,另一条费用为那个点处的值.流量都限制为1.然后剩下的都跟杭电上的那两个差不多了.因为把数组开小了WA了好几发..(我前面居然还专门检查了一下数组大小,居然当时还认为没开小...对自己无语..) 代码如下: #include <iostream> #include <stdio.h> #include &l

HDU 4406 GPA(网络流-最大费用流)

GPA Problem Description GPA(Grade-Point Average) is one way to measure students' academic performance in PKU. Each course has an integer credit, ranges from 1 to 99. For each course, you will get a score at the end of the semester, which is an intege

网络流之费用流问题

费用流即最小费用最大流 先贴上粉书上的模板: struct Edge { int from,to,cap,flow,cost; Edge(int u,int v,int c,int f,int w): from(u),to(v),cap(c),flow(f),cost(w) {} }; int n,m; vector<Edge> edges; vector<int> G[maxn]; int inq[maxn]; int d[maxn]; int p[maxn]; int a[ma

HDU 3667 Transportation(网络流之费用流)

题目地址:HDU 3667 这题的建图真是巧妙...为了保证流量正好达到k,需要让每一次增广到的流量都是1,这就需要把每一条边的流量都是1才行.但是每条边的流量并不是1,该怎么办呢.这个时候可以拆边,反正c最多只有5,拆成5条流量为1的边.但是这时候费用怎么办呢,毕竟平方的关系不能简单把每一条边加起来.这时候可以把拆的边的流量设为1,3,5,7,9.如果经过了3个流量,那就肯定会流1,3,5,费用为9,是3的平方,同理,其他的也是如此.然后按照给出的边建图跑一次费用流就可以了. 代码如下: #i

POJ 2516 Minimum Cost(网络流之费用流)

题目地址:POJ 2516 我晕啊...这题一上来就想到了对每种货物分开求..但是马上就放弃了..感觉这样求50次费用流太耗时..后来就果断拆点,拆了好长时间,一直TLE..即使降到了2600个点也TLE..然后又想起了这个分开求的方法,又突然觉得100个点的费用流几乎不费什么时间..最多也只是求50次而已,还是可以试试的..于是一试居然还真过了... 说到这里,思路应该已经知道了吧.就是对每种货物分开求,因为每种货物是相互独立的.每一次的建图思路就是: 源点与供应商连边,流量权值为供应商这种货

POJ 3422 Kaka&#39;s Matrix Travels(网络流之费用流)

题目地址:POJ 3422 方法是对每个点i拆点成i'和i'',然后对每个i'和i''连一条费用为该点值,流量为1的边,再连1条费用为0,流量为k-1的边. 然后对每个点与右边下边相邻的点连边,流量均为INF,费用均为0.需要再建一源点与汇点,对于k次只需要在源点与汇点处进行限制即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #inclu

有上下界的、有多组源汇的、网络流、费用流问题

先默认读者有基础的网络流以及费用流的知识前置 1.有上下界无源点汇点的可行流问题: 在本文中指: 原图中没有任何一个点可以凭空产生流量,亦没有任何一个点可以凭空消灭流量: 存在边既有流量上界又有流量下界: 求每条边流量的一组可行解: 满足每个点的入流量等于出流量: 由题意可见本题的图中有环,于是此类问题也被称作循环流: 这里给出的解法是将本题转换为一道普通的有上界最大流问题: 修改本题原图中每条边的流量下界为0,上界为原上界-原下界: 视为该边现在已经拥有了等同于该边流量下界的基础流量了, 然而

洛谷P4003 无限之环(infinityloop)(网络流,费用流)

洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ? m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格子某些方向的边界的中点有接口,所有水管的粗细都相同,所以如果两个相邻方格的共边界的中点都有接头,那么可以看作这两个接头互相连接.水管有以下 15 种形状: 游戏开始时,棋盘中水管可能存在漏水的地方. 形式化地:如果存在某个接头,没有和其它接头相连接,那么它就是一个漏水的地方. 玩家可以进行一种操作:

HDU 2686 &amp;&amp; HDU 3376(网络流之费用流)

题目地址:HDU 2686       HDU 3376 这两道题目除了数据大小外是一样的.前者只有30*30,但是后者却成了600*600..本来以为前者代码用到后者会超时,迟迟没敢交,但是感觉能用费用流的话也只能这么做了,于是改了改数组大小就交上去了.还真没超时.. 这题又是一道关于来回最短路的.最大费用可以把费用改成相反数,最后再转成相反数就是最大费用了. 建图思路是拆点,限制每个点只能经过一次.然后将每个点与右边的和下边的连边.源点与汇点要设为2个流量. 不知道为什么用G++叫就一直WA