zoukankan      html  css  js  c++  java
  • 终极情报网 题解

    首先建立源点和汇点,然后建一个辅助源点,让源点和辅助源点之间连一条流量为(k),费用为(1)的边,表示最多增广(k)次。
    接下来对于那些和总部联通的人,流量即为最大传递消息数量,费用为这次的安全程度。
    对于任意(2)个能联系的人,按照相同的方法处理。
    那些和敌军情报部门能联系的人和汇点连边,流量为(k),费用也为(1)
    这样我们就初步建出了一张图,考虑最后的答案,设(F_{i,j})(i,j)之间传递信息的实际数目,(S_{i,j})(i,j)传递消息的安全程度,(A_i)为总部和这个点传递信息的数目,(P_i)为总部和这个点联系的安全程度,那么答案就是(max{prod_{i=1}^nprod_{j=1}^nS_{i,j}^{F_{i,j}}prod_{i=1}^nA_i^{P_i}}),我们考虑对边权取对数,那么最后的答案就化为了(min{sum_{i=1}^nsum_{j=1}^n(-F_{i,j} imes ln(S_{i,j}))+sum_{i=1}^n(-P_i imes ln{A_i})})
    现在问题就转化为了求和,可以用最小费用最大流求解。

    #include <bits/stdc++.h>
    #define eps 1e-12
    int n,k;
    int S=1,cloneS=2,T=3;
    int Max_flow[301],call[301],vis[301],flow[301],last_edge[301];
    double proA[301],dis[301];
    int head[1000000],tot=1;
    std::queue<int>q;
    struct edge{
    	int to;
    	int nxt;
    	int flow;
    	double cost;
    }e[1000000];
    void add(int x,int y,int flow,double cost){
    	e[++tot]={y,head[x],flow,cost};
    	head[x]=tot;
    	e[++tot]={x,head[y],0,-cost};
    	head[y]=tot;
    }
    bool spfa(){
    	for(int i=1;i<=n+3;++i){
    	  dis[i]=-100;
    	  vis[i]=0;
    	}
    	dis[S]=0;
    	flow[S]=k;
    	last_edge[S]=-1;
    	q.push(S);
    	while(!q.empty()){
    		int x=q.front();
    		q.pop();
    		vis[x]=0;
    		for(int i=head[x];i;i=e[i].nxt){
    			int y=e[i].to;
    			if(e[i].flow&&dis[y]+eps<dis[x]+e[i].cost){
    				dis[y]=dis[x]+e[i].cost;
    				flow[y]=std::min(e[i].flow,flow[x]);
    				last_edge[y]=i;
    				if(!vis[y]){
    					vis[y]=1;
    					q.push(y);
    				}
    			}
    		}
    	}
      if(fabs(dis[T]+100.0)<eps)
        return 0;
      return 1;
    }
    void deal(double ans){
      char ch[40];
      sprintf(ch,"%.15f
    ",ans);
      int sum=0,i;
      for(i=0;sum<5;i++)
        if((ch[i]!='0'&&ch[i]!='.')|sum>0)
          sum++;
      if(ch[i]>='5')
        ch[i-1]++;
      ch[i]=0;
      for(;i>=0;i--)
        if(ch[i]=='.')
    		  break;
        else 
    		  if(ch[i]>'9')
            ch[i-1]++,ch[i]='0';
      printf("%s
    ",ch);
    }
    void dinic(){
    	int Flow=0;
    	double cost=0;
    	while(spfa()){
    		cost+=dis[T]*flow[T];
    		Flow+=flow[T];
    		for(int i=last_edge[T];~i;i=last_edge[e[i^1].to]){
    			e[i].flow-=flow[T];
    			e[i^1].flow+=flow[T];
    		}
    	}
    	if(Flow!=k){
    		puts("0.00000000");
    		return;
    	}
    	else{
    		cost=std::exp(cost);
    		deal(cost);
    	}
    }
    main(){
    	scanf("%d%d",&n,&k);
    	add(S,cloneS,k,log(1.0));
    	for(int i=1;i<=n;++i)
    	  scanf("%lf",&proA[i]);
    	for(int i=1;i<=n;++i){
    	  scanf("%d",&Max_flow[i]);
    	  if(proA[i])
    	  	add(cloneS,i+3,Max_flow[i],log(proA[i]));
    	}
    	for(int i=1;i<=n;++i){
    		scanf("%d",&call[i]);
    		if(call[i])
    		  add(i+3,T,k,log(1.0));
    	}
    	while(true){
    		int spyA,spyB;
    		double pro;
    		int Maxflow;
    		scanf("%d%d",&spyA,&spyB);
    		if(spyA+spyB==-2)
    		  break;
    		scanf("%lf%d",&pro,&Maxflow);
    		add(spyA+3,spyB+3,Maxflow,log(pro));
    		add(spyB+3,spyA+3,Maxflow,log(pro));
    	}
    	dinic();
    	return 0;
    }
    
  • 相关阅读:
    软件工程课程总结
    《20171122-构建之法:现代软件工程-阅读笔记》
    课后作业-阅读任务-阅读提问-4
    20171012-构建之法:现代软件工程-阅读笔记
    课后作业-阅读任务-阅读提问-2
    《20170911-构建之法:现代软件工程-阅读笔记》
    OSI七层模型
    团队编程项目作业名称-团队一阶段互评
    结对-结对编程项目作业名称-结对项目总结
    团队-团队编程项目作业名称-开发文档
  • 原文地址:https://www.cnblogs.com/Skylight/p/13049668.html
Copyright © 2011-2022 走看看