• 【费用流】hdu5988 Coding Contest


    从源点向每个点连接容量为该点人数,费用为1的边,

    把原图中的每条边拆成两条,一条容量为1,费用为1,另一条容量为ci-1,费用为1-pi

    从每个点向汇点连接容量为该点面包数量,费用为1的边。

    跑的费用流为按照乘积跑个最大费用流。

    可以取个对数,乘法变成加法,

    可以再取个负数,最大费用变成最小费用。

    别忘了最后还原回来。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<cmath>
    using namespace std;
    #define E 2.71828182845904523536
    #define EPS 0.00000001
    #define MAXN 201
    #define MAXM 25001
    #define INF 2147483647
    int S,T;
    int en,u[MAXM],v[MAXM],first[MAXN],__next[MAXM],cap[MAXM];
    double cost[MAXM];//__next Array
    bool 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;
        __next[en]=first[U]; first[U]=en++;
        u[en]=V; v[en]=U; cap[en]=0; cost[en]=-C;
        __next[en]=first[V]; first[V]=en++;
    }
    bool Spfa(int &Flow,double &Cost)
    {
        memset(d,0x7f,sizeof(d));
        memset(inq,0,sizeof(inq));
        d[S]=0; inq[S]=1; p[S]=0; a[S]=INF; q.push(S);
        while(!q.empty())
          {
              int U=q.front(); q.pop(); inq[U]=0;
              for(int i=first[U];i!=-1;i=__next[i])
                if(cap[i] && d[v[i]]-(d[U]+cost[i])>EPS)
                  {
                    d[v[i]]=d[U]+cost[i];
                    p[v[i]]=i;
                    a[v[i]]=min(a[U],cap[i]);
                    if(!inq[v[i]]) {q.push(v[i]); inq[v[i]]=1;}
                  }
          }
        if(d[T]-2000000000.0>EPS) return 0;
        Flow+=a[T]; Cost+=d[T]*(double)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));
        return Cost;
    }
    int Zu,n,m;
    int main(){
    //	freopen("g.in","r",stdin);
    	int x,y,z;
    	double p;
    	scanf("%d",&Zu);
    	for(int zu=1;zu<=Zu;++zu){
    		Init_MCMF();
    		scanf("%d%d",&n,&m);
    		S=n+1; T=n+2;
    		for(int i=1;i<=n;++i){
    			scanf("%d%d",&x,&y);
    			AddEdge(S,i,x,0);
    			AddEdge(i,T,y,0);
    		}
    		for(int i=1;i<=m;++i){
    			scanf("%d%d%d%lf",&x,&y,&z,&p);
    			if(z>0){
    				AddEdge(x,y,1,0);
    				AddEdge(x,y,z-1,-log(1.0-p));
    			}
    		}
    		printf("%.2lf
    ",1.0-pow(E,-Mincost()));
    	}
    	return 0;
    }
  • 相关阅读:
    [Micropython]发光二极管制作炫彩跑马灯
    如何在MicroPython TPYBoard 添加自定义类库
    micropython TPYBoard v202 超声波测距
    简易排水简车的制作 TurnipBit 系列教程
    TPYBoard v102 驱动28BYJ-48步进电机
    使用mksdcard管理虚拟SD卡
    使用 DX 编译 Android应用
    常用ADB的用法
    在命令行创建、删除和浏览AVD、使用android模拟器
    Android-SDK下目录结构
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6683107.html
Copyright © 2020-2023  润新知