• ACM ICPC 2017 WF Problem J Son of Pipe Stream题解


    ACM ICPC 2017 WF Problem J Son of Pipe Stream

    一个神仙网络流题。

    首先一个直观的想法:可以枚举水的多少,然后让flubber尽量多。

    然后再慢慢调整当前的策略。

    假设当前的候选答案为(w,f)。(表示水和flubber的数量)

    若,当前在保证一个数不变的情况下可以增大另一个数,则这个一定不是最优解。

    否则在增加一个数的同时另一个数会减小。可以发现一个数增加的数=另一个数减少的数。

    所以两个数的总和不变。

    另一个发现,两个加起来等于(maxflow)

    不然一定可以在保证(s)到其中一个源不退流而增广另一个。

    然后就可以得到可行的备选最优解((w,f))组成的直线。

    然后可以发现那个函数是单峰的。然后就直接实数三分就好了。(防止精度误差,可以取(ln)

    code:

    /*
    {
    ######################
    #       Author       #
    #        Gary        #
    #        2020        #
    ######################
    */
    #include<bits/stdc++.h>
    #define rb(a,b,c) for(int a=b;a<=c;++a)
    #define rl(a,b,c) for(int a=b;a>=c;--a)
    #define LL long long
    #define IT iterator
    #define PB push_back
    #define II(a,b) make_pair(a,b)
    #define FIR first
    #define SEC second
    #define FREO freopen("check.out","w",stdout)
    #define rep(a,b) for(int a=0;a<b;++a)
    #define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
    #define random(a) rng()%a
    #define ALL(a) a.begin(),a.end()
    #define POB pop_back
    #define ff fflush(stdout)
    #define fastio ios::sync_with_stdio(false)
    #define check_min(a,b) a=min(a,b)
    #define check_max(a,b) a=max(a,b)
    using namespace std;
    //inline int read(){
    //    int x=0;
    //    char ch=getchar();
    //    while(ch<'0'||ch>'9'){
    //        ch=getchar();
    //    }
    //    while(ch>='0'&&ch<='9'){
    //        x=(x<<1)+(x<<3)+(ch^48);
    //        ch=getchar();
    //    }
    //    return x;
    //}
    const int INF=0x3f3f3f3f;
    typedef pair<int,int> mp;
    /*}
    
    */
    const int GRAPH_SIZE=250 ;
    int pin[GRAPH_SIZE],dep[GRAPH_SIZE],s=0,t=GRAPH_SIZE-1;
    struct EDGE{
    	int u,v;
    	double c;
    };
    vector<EDGE> e;
    vector<int> each[GRAPH_SIZE];
    bool bfs(){
    	queue<int> Q;
    	Q.push(s);
    	while(!Q.empty()){
    		int now=Q.front();
    		Q.pop();
    		for(auto it:each[now]){
    			int next=e[it].v;
    			if(e[it].c)
    			if(dep[next]>dep[now]+1){
    				dep[next]=dep[now]+1;
    				Q.push(next);
    			}
    		}
    	}
    	return dep[t]!=INF;
    }
    double dfs(int now,double flow){
    	if(now==t){
    		return flow;
    	}
    	for(int & i= pin[now];i<each[now].size();i++){
    		int it=each[now][i];
    		if(e[it].c&&dep[e[it].v]==dep[now]+1){
    			double tmp;
    			if(tmp=dfs(e[it].v,min(double(flow),e[it].c))){
    				e[it].c-=tmp;
    				e[it^1].c+=tmp;
    				return tmp;
    			}
    		}
    	}
    	return 0;
    }
    int Dinic(){
    	int max_flow=0;
    	rep(i,GRAPH_SIZE)
    	{
    		
    		dep[i]=INF;
    	}
    	dep[s]=0;
    	while(bfs()){
    		rep(i,GRAPH_SIZE){
    			pin[i]=0;
    		}
    		double tmp;
    		while(tmp=dfs(s,INF)){
    			max_flow+=tmp;
    		}
    		rep(i,GRAPH_SIZE){
    			dep[i]=INF;
    		}
    		dep[s]=0;
    	}
    	return max_flow;
    }
    void make_edge(int U,int V,double C){
    	EDGE tmp;
    	tmp.u=U;
    	tmp.v=V;
    	tmp.c=C;
    	e.PB(tmp);
    	each[U].PB(e.size()-1);
    	swap(tmp.u,tmp.v);
    	tmp.c=0;
    	e.PB(tmp);
    	each[V].PB(e.size()-1);
    }
    void init(){
    	e.clear();
    	rep(i,GRAPH_SIZE){
    		each[i].clear();
    	}
    }
    int n,p;
    double v,a;
    double sum;
    double water[100000],flubber[100000];
    map<mp,int> is;
    double calc(double x){
    	return log(pow(x,a))+log(pow(sum-x,1.0-a));
    }
    void go(int now,double N,bool flub){
    	if(N==0) return;
    	for(auto it:each[now]){
    		if(it&1) continue;
    		if(e[it^1].c){
    			double& z=e[it^1].c;
    			int id=is[II(e[it].u,e[it].v)];
    			double t=min(z,N);
    			z-=t;
    			N-=t;
    			if(flub){
    				if(id<0){
    					id*=-1;
    					flubber[id]-=t;
    					go(e[it].v,t,flub);
    				}
    				else{
    					flubber[id]+=t;
    					go(e[it].v,t,flub);
    				}
    			}
    			else{
    				if(id<0){
    					id*=-1;
    					water[id]-=t;
    					go(e[it].v,t,flub);
    				}	
    				else{
    					water[id]+=t;
    					go(e[it].v,t,flub);
    				} 
    			}
    		}
    	}
    }
    vector<pair<mp,int> > edges;
    void construct(double f){
    	init();
    	for(auto it:edges){
    		make_edge(it.FIR.SEC,it.FIR.FIR,it.SEC);
    		make_edge(it.FIR.FIR,it.FIR.SEC,it.SEC);
    	}
    	make_edge(s,1,f);
    	make_edge(s,2,sum-f);
    	make_edge(3,t,INF);
    	Dinic();
    	go(1,f,1);
    	go(2,sum-f,0);
    }
    int main(){
    	scanf("%d%d",&n,&p);
    	scanf("%lf%lf",&v,&a);
    	rb(i,1,p){
    		int j,k,c;
    		scanf("%d%d%d",&j,&k,&c);
    		edges.PB(II(II(j,k),c));
    		is[II(j,k)]=i;
    		is[II(k,j)]=-i;
    		make_edge(j,k,c);
    		make_edge(k,j,c);
    		flubber[i]=water[i]=0.0;
    	}
    	make_edge(s,1,INF);
    	make_edge(3,t,INF);
    	Dinic();
    	make_edge(s,2,INF);
    	Dinic();
    	int fm,wn,fn,wm;
    	for(auto it:each[s]){
    		if(e[it].v==1){
    			fm=e[it^1].c;
    		}
    		else{
    			wn=e[it^1].c;
    		}
    	}
    	init();
    	for(auto it:edges){
    		make_edge(it.FIR.SEC,it.FIR.FIR,it.SEC);
    		make_edge(it.FIR.FIR,it.FIR.SEC,it.SEC);
    	}
    	make_edge(s,2,INF);
    	make_edge(3,t,INF);
    	Dinic();
    	make_edge(s,1,INF);
    	Dinic();
    	for(auto it:each[s]){
    		if(e[it].v==1){
    			fn=e[it^1].c;
    		}
    		else{
    			wm=e[it^1].c;
    		}
    	}
    	double rest=0.0;
    	sum=fm+wn;
    	double l,r;
    	l=fn,r=fm;
    	while(l+(1e-9)<r){
    		double mid=(l+r)/2.0;
    		if(calc(mid)<calc(mid+(1e-9))){
    			l=mid+1e-9;
    		}
    		else{
    			r=mid;
    		}
    	}
    	construct(l);
    	rest=pow(l,a)*pow(sum-l,1.0-a);
    	rb(i,1,p){
    		printf("%.10f %.10f
    ",flubber[i]/v,water[i]);
    	}
    	printf("%.10f
    ",rest*pow(v,-a));
    	return 0;
    }
    
  • 相关阅读:
    1.5 判断是奇数还是偶数(比较运算符 & if...else)
    1.4计算器 (数字类型 & 算术运算符 &赋值运算符)
    1.3hello 张三(终端交互 & 字符串)
    1.2python语言环境 & python IDE(集成开发环境)搭建
    Centos 7 下安装jdk 7
    Centos 7 安装redis
    git 学习笔记
    git 基础操作
    git 获取远程分支的代码
    redis基础操作
  • 原文地址:https://www.cnblogs.com/gary-2005/p/14130832.html
Copyright © 2020-2023  润新知