【费用流】double模板

来源:互联网 发布:java facet 是什么 编辑:程序博客网 时间:2024/05/17 02:42

https://vjudge.net/contest/201468#problem/G
一道费用流,原版来自通酱,被zzb魔改为可用于费用为double
http://www.cnblogs.com/autsky-jadek/p/4149096.html

#include<cstdio>#include <iostream>#include<algorithm>#include<cstring>#include<queue>using namespace std;#define MAXN 111#define MAXM 22001#define INF 2147483647int S,T,n,m;int en,u[MAXM],v[MAXM],first[MAXN],nex[MAXM],cap[MAXM];double cost[MAXM];//Next Arraybool inq[MAXN];double d[MAXN]/*spfa*/;int p[MAXN]/*spfa*/,a[MAXN]/*可改进量*/;queue<int>q;void Init_MCMF(){memset(first,-1,sizeof(first));en=0;}void AddEdge(const int &U,const int &V,const int &W,const double &C){    u[en]=U; v[en]=V; cap[en]=W; cost[en]=C;    nex[en]=first[U]; first[U]=en++;    u[en]=V; v[en]=U; cap[en]=0; cost[en]=-C;    nex[en]=first[V]; first[V]=en++;}bool check[ MAXN ];bool Spfa(int &Flow,double &Cost){    memset(check , 0 ,sizeof( check ) );    bool op=0;    memset(inq,0,sizeof(inq));    d[S]=0; inq[S]=1; p[S]=0; a[S]=INF; q.push(S);    check[S]=1;    while(!q.empty())      {          int U=q.front(); q.pop(); inq[U]=0;          for(int i=first[U];i!=-1;i=nex[i])            if(cap[i] && ( ( check[v[i]]==0)|| (  d[v[i]] > 1e-7+ d[U]+cost[i] ) ) )              {                d[v[i]]=d[U]+cost[i];                check[v[i]]=1;                p[v[i]]=i;                a[v[i]]=min(a[U],cap[i]);                if ( v[i] == T )                    op=1;                if(!inq[v[i]]) {q.push(v[i]); inq[v[i]]=1;}              }      }    if ( op==0 )        return 0;    //if( fabs( d[T] - 2000000000)<1e-5 )return 0;    Flow+=a[T]; Cost+=d[T]*a[T]; int U=T;    while(U!=S)      {          cap[p[U]]-=a[T]; cap[p[U]^1]+=a[T];          U=u[p[U]];      }    return 1;}double Mincost(){    int Flow=0;    double Cost=0;    while(Spfa(Flow,Cost));    //printf("%d\n",Flow);    return Cost;}void doit(){Init_MCMF();scanf("%d%d",&n,&m);S=n+1;T=n+2;for (int i=1;i<=n;i++)    {        int a,b;        scanf("%d%d",&a,&b);        AddEdge(S,i,a,0);        AddEdge(i,T,b,0);    }for (int i=1;i<=m;i++)    {        int a,b,c;        double d;        scanf("%d%d%d%lf",&a,&b,&c,&d);        if ( c )        {            d=-log(1-d);            //cout<<d<<endl;            if ( c>1)                AddEdge(a,b,c-1,d);            AddEdge(a,b,1,0);        }    }printf("%.2f\n",1-exp( -Mincost()  ) );}int main(){    int T;    scanf("%d",&T);    for (int i=1;i<=T;i++)        doit();    return 0;}