BZOJ 3130 Sdoi2013 费用流

本文详细解析了SDOI2013费用流问题,介绍了最大流和最小费用最大流的概念,通过示例解释了如何在给定网络中找到最大流值和最小总费用,使用网络流算法结合实数二分法解决复杂问题。

3130: [Sdoi2013]费用流

Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 1406  Solved: 679
[Submit][Status][Discuss]

Description

 Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识。
    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量。一个合法的网络流方案必须满足:(1)每条边的实际流量都不超过其最大流量且非负;(2)除了源点S和汇点T之外,对于其余所有点,都满足该点总流入流量等于该点总流出流量;而S点的净流出流量等于T点的净流入流量,这个值也即该网络流方案的总运输量。最大流问题就是对于给定的运输网络,求总运输量最大的网络流方案。


  上图表示了一个最大流问题。对于每条边,右边的数代表该边的最大流量,左边的数代表在最优解中,该边的实际流量。需要注意到,一个最大流问题的解可能不是唯一的。    对于一张给定的运输网络,Alice先确定一个最大流,如果有多种解,Alice可以任选一种;之后Bob在每条边上分配单位花费(单位花费必须是非负实数),要求所有边的单位花费之和等于P。总费用等于每一条边的实际流量乘以该边的单位花费。需要注意到,Bob在分配单位花费之前,已经知道Alice所给出的最大流方案。现茌Alice希望总费用尽量小,而Bob希望总费用尽量大。我们想知道,如果两个人都执行最优策略,最大流的值和总费用分别为多少。

Input

    第一行三个整数N,M,P。N表示给定运输网络中节点的数量,M表示有向边的数量,P的含义见问题描述部分。为了简化问题,我们假设源点S是点1,汇点T是点N。
    接下来M行,每行三个整数A,B,C,表示有一条从点A到点B的有向边,其最大流量是C。

Output

第一行一个整数,表示最大流的值。
第二行一个实数,表示总费用。建议选手输出四位以上小数。

Sample Input

3 2 1
1 2 10
2 3 15

Sample Output

10
10.0000

HINT

 

【样例说明】

    对于Alice,最大流的方案是固定的。两条边的实际流量都为10。

    对于Bob,给第一条边分配0.5的费用,第二条边分配0.5的费用。总费用

为:10*0.5+10*0.5=10。可以证明不存在总费用更大的分配方案。

【数据规模和约定】

    对于20%的测试数据:所有有向边的最大流量都是1。

    对于100%的测试数据:N < = 100,M < = 1000。

    对于l00%的测试数据:所有点的编号在I..N范围内。1 < = 每条边的最大流

量 < = 50000。1 < = P < = 10。给定运输网络中不会有起点和终点相同的边。

 

Source

本来以为这是一道很水的题目,其实就是很水,裸地网络流+实数二分

何为实数二分呢,就是二分double类型的数

直接赋值并不进行加一减一的操作,因为一些小错误我调了半天,妈的

#include <bits/stdc++.h>
#define ll long long 
#define eps 1e-5
using namespace std;
inline int read(){
    int x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=2e3+10;
struct node{
    int x,y,next,back;
    double flow;
}e[MAXN<<1],s[MAXN];
int linkk[MAXN<<1],level[MAXN],len=0,n,m,p;
inline void insert(int xx,int yy,double f){
    e[++len].y=yy;e[len].next=linkk[xx];linkk[xx]=len;e[len].flow=f;e[len].back=len+1;
    e[++len].y=xx;e[len].next=linkk[yy];linkk[yy]=len;e[len].flow=0;e[len].back=len-1;
}
inline void build(double num){
    memset(linkk,0,sizeof(linkk));
    len=0;
    for(int i=1;i<=m;i++){
        insert(s[i].x,s[i].y,min(num,s[i].flow));
    }
}
void init(){
    n=read();m=read();p=read();
    for(int i=1;i<=m;i++){
        s[i].x=read();s[i].y=read();s[i].flow=read();
    }
    build(23712837);
}
int q[MAXN<<4],head,tail;
inline bool getlevel(){
    memset(level,-1,sizeof(level));
    head=tail=0;
    q[++tail]=1;
    level[1]=0;
    while(head<tail){
        int tn=q[++head];
        for(int i=linkk[tn];i;i=e[i].next){
            if(level[e[i].y]==-1&&e[i].flow){
                level[e[i].y]=level[tn]+1;
                q[++tail]=e[i].y;
            }
        }
    }
    return level[n]>=0;
}
inline double getmaxflow(int st,double flow){
    if(st==n) return flow;
    double maxflow=0;double d=0;
    for(int i=linkk[st];i&&maxflow<flow;i=e[i].next){
        if(level[e[i].y]==level[st]+1&&e[i].flow>0){
            if(d=getmaxflow(e[i].y,min(flow-maxflow,e[i].flow))){
                e[i].flow-=d;
                e[e[i].back].flow+=d;
                maxflow+=d;
            }
        }
    }
    if(!maxflow) level[st]=-1;
    return maxflow;
}
inline double dinic(){
    double sum=0;double ans;
    while(getlevel()){
        while(ans=getmaxflow(1,312323233)){
            sum+=ans;
        }
    }
    return sum;
}
int main(){
    //freopen("All.in","r",stdin);
    //freopen("zhang.out","w",stdout);
    init();
    double k=dinic();
    cout<<k<<endl;
    double l=0;double r=0;
    for(int i=1;i<=m;i++){
        r=max(r,s[i].flow);
    }
    while((r-l)>eps){
        //printf("%lf %lf\n",l,r);
        double mid=(l+r)*0.5;
        build(mid);
        double t=dinic();
        if(abs(t-k)<eps) r=mid;
        else l=mid;
    }
    printf("%.4f\n",l*p);
    return 0;
}
//对拍代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
    ll x=0;ll f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main(){
    srand(time(int(NULL)));
    freopen("All.in","w",stdout);
    int n=rand()%107+1;int m=rand()%1007+n;int T=rand()%57;
    cout<<n<<' '<<m<<' '<<T<<endl;
    cout<<rand()%n+1<<' '<<rand()%m+1<<' '<<T<<endl;
    for(int i=1;i<=m;i++){
        int xx=rand()%n+1;
        int yy=rand()%n+1;
        int vv=rand()%107;
        printf("%d %d %d\n",xx,yy,vv);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/something-for-nothing/p/7941393.html

《java面试800题(包括java,数据库,前台等,绝对全面)》 Q0027 哪些SQL语句在执行时是自动提交的? 数据定义语言DDL是自动提交的。 Q0028 索引对数据库的影响? 提高查询速度 Q0029 主外键有什么关系? 外键是从某个表的一个字段指向另外一个表的主健字段,两个字段的类型和精度应该一致,外键的值必须在主键中存在 Q0030 在数据库中什么代表一条记录? 主健 Q0031 如何编写效率高的SQL语句? "1.根据查询条件建立合适的index 2.因为SQL是从右向左解析,多表查询时,记录数少的表放在右边 3.多个条件时,收敛快的条件放在右边。 4.避免使用复杂的集合函数,象not in等。 5.避免在条件中对字段进行函数操作 6.尽量避免使用select *,应该写出需要查询的字段 7.在java中尽量使用preparestatement执行sql,从而共享执行计划" Q0032 Oracle的集合操作函数,如sum(),avg(),max(),min(),与select,where,grouby,having的先后顺序,使用方法 Oracle集合查询基本知识,只有进行分组的列,才可以取在集合查询SQL语句中取字段,先Group By,再Having作为集合查询的条件 Q0033 在Oracle数据库中,给定一个表,其中一列有索引,现在用这个列作为查询条件,因为用到了索引,速度一定会快吗? 答案是否定的,比如在这个列中使用‘%sdfd%’来进行模糊查询 Q0034 给定了一些创建数据库试图的SQL语句问什么条件下才可以对试图执行修改,增加,删除操作 特别强调了WITH CHECK OPTION这个约束的含义,使用,产生的不同结果。参考Oracle 视图的基本知识,单个表上的视图,多个表的联合试图,更新视图与表之间的关系.http://www.gzu521.com/it/oracle/zonghe/200904/20748_2.htm Q0035 是不是表或者其他对象不存在,就一定不能在Oracle中创建视图? 否,可通过FORCE选项执行强制生成视图,好处是在表不存在的时候,先创建视图 Q0036 如何创建oracle函数索引 "SQL>create index non_fbi on sale_contacts (surname); SQL>analyze index non_fbi compute statistics; SQL>:analyze table sale_contacts compute statistics; SQL>SELECT count(*) FROM sale_contacts WHERE UPPER(surname) = 'ELLISON'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=17) 1 0 SORT (AGGREGATE) 2 1 TABLE ACCESS (FULL) OF 'SALES_CONTACTS' (Cost=3 Card=16 Bytes=272) " Q0037 "ORACLE锁的管理 " "ORACLE里锁有以下几种模式: 0:none 1:null 空 2:Row-S 行共享(RS):共享表锁 3:Row-X 行专用(RX):用于行的修改 4:Share 共享锁(S):阻止其他DML操作 5:S/Row-X 共享行专用(SRX):阻止其他事务操作 6:exclusive 专用(X):独立访问使用 数字越大锁级别越高, 影响的操作越多。" Q0038 创建XML文件的格式? " …" Q0039 java接口与抽象类的区别 "1.接口可以多重继承 ,抽象类不可以 2.接口定义方法,不给实现;而抽象类可以实现部分方法 3.接口中基本数据类型的数据成员,都默认为static和final,抽象类则不是 如果事先知道某种东西会成为基础类, 那么第一个选择就是把它变成一个接口。 只有在必须使用方法定义或者成员变量的时候,才应考虑采用抽象类。" Q0040 Java关键字 "51个:abstract, boolean, break, byte, case, catch, char, class, const, continue, default, do, double, else, extends, final, finally, float, for, goto, if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, try, void, volatile, while. " Q0041 Java保留字 11个:byValue, cast, false, future, generic, inner, operator, outer, rest, true, var. Q0042 Java的值传递的规则? Java基本类型的都是值传递,对象使用的都是引用传递 Q0043 java相关概念 "static:静态,无需实例化,可直接引用,全局只有一份copy,修饰变量和方法 final:最终的,不可继承、不可修改,修饰变量、方法、类 volatile:volatile变量表示保证它必须是与主内存保持一致,它实际是""变量的同步"", 也就是说对于volatile变量的操作是原子型的,如用在long 或 double变量前,一般用于多线程编程。 abstract:抽象,必须重载,修饰类和方法 native:把java代码和其他语言的代码集成起来 synchronized:控制多个并发线程对共享数据的访问 throwsException:异常处理" Q0044 this&super的异同 "this :引用当前对象 super:引用当前对象的父类 使用情况: (1) super.variable //用来访问父类被隐藏的成员变量 (2) super.Method([paramlist]) //用来调用父类中被重载的方法 (3) super.([paramlist]) //调用父类中的构造函数 在类方法中(static),不能使用this或super修饰符 " Q0045 Java中是怎样捕获异常的? "try { //statement01 } catch(Exception e) { //statement02 } finally { //statement03 }" Q0046 一个文件中是否可以有多个public类? 不可以 Q0047 子类是否可以访问父类的私有成员? 不可以 Q0048 NULL是否是Java的关键字? 不是。null,false,true是保留字 Q0049 一个有序数组和一个无序数组,从无序数组中取出每条记录与有序数组比较,如果符合条件,把无序数组中的值加入到有序数组中,问这是什么排序? 插入排序法 Q0050 程序与进程的区别? 程序是为了完成某种任务而设计的软件,比如OpenOffice是程序。什么是进程呢?进程就是 运行中的程序。 一个运行着的程序,可能有多个进程。 Q0051 设计模式主要几种 "创建模式 factory工厂模式、prototype原始模型模式、singleton单例模式、builder建造模式 结构模式 facade门面模式、proxy代理模式、adapter适配器(变压器)模式、composite合成模式、decorator装饰模式、bridge桥梁模式、flyweight享元模式 行为模式 template模板方法模式、memento备忘录模式、observer观察者模式、command命令模式、state状态模式、strategy策略模式、mediator调停者模式、interpreter解释器模式、visitor访问者模式、chain of responsibility责任链模式" Q0052 构造函数的相关知识? "构造函数(constructor )在对象创建时初始化。 构造函数是和类同名的函数,没有返回类型,构造函数不能在普通的程序里面调用,只有当这个类被应用new实例化的时候才会被运行。构造函数没有返回类型,实际上,构造函数返回的就是这个class本身。 类初始化时构造函数调用顺序: (1)初始化对象的存储空间为零或null值; (2)调用父类构造函数; (3)按顺序分别调用类成员变量和实例成员变量的初始化表达式; (4)调用本身构造函数。" Q0053 "Public class Servlet extends HttpServlet{ int i; doget(){ i++; out.print(i); } } 每次访问时i是否变化?" 会 Q0054 类的加载过程? "类的初始化过程 当创建一个对象时,对象的各个变量根据其类型被设置为相应的默认初始值,然后调用构造方法,而每次调用构造方法都是要执行三个阶段: 1.调用超类的构造方法; 2.由初始化语句对给变量进行初始化; 3.执行构造方法的体。" Q0055 系统运行时的最小单位是什么? 线程 Q0056 Java的编码规范? Q0057 Java的命名规范? Q0058 一个Java抽象类声明了一个方法并会抛出一个异常,问继承这个抽象类的子类,实现了这个方法,这个方法声明是不是一定要抛出一模一样的异常,可不可以不抛,或者抛出的异常比抽象类的异常范围大,或者小? 可以不抛,或者比抽象类的小,但绝对不能抛出的异常比抽象类的大 Q0059 找出weblogic-ejb-jar.xml文件中的错误。 "正确的文档 Catalog WebLogic_CMP_RDBMS 7.0 META-INF/weblogic-cmp-rdbms-jar.xml com.ejb.CatalogHome " Q0060 JDBC批量更新的作用和用法 "提高执行效率。减少执行时间。 Statement sm = cn.createStatement(); sm.addBatch(sql1); sm.addBatch(sql2); ... sm.executeBatch() 或者 PreparedStatement ps = cn.preparedStatement(sql); { ps.setXXX(1,xxx); ... ps.addBatch(); } ps.executeBatch();" Q0061 事务的特性是什么? "事务有四种特性:ACID Atomicity(原子性) 事务中的操作或者全部完成,或者全部不完成。 Consistency(一致性) 事务执行的结果是从一个一致性状态转移到另一个一致性状态。 Isolation(隔离性) 一个事务的执行不能被其它事务干扰,即并发事务间内部数据是隔离的。 Durability(持久性) 事务开始执行后,它对系统中数据的改变应该是恒定的,不应受其它操作或故障的影响。 " Q0062 事务有几种属性?分别是什么? "事务的属性有6种 1.Required:当处于事务范围内的客户端应用调用组件商务方法时,组件商务方法执行在原有的客户端事务范围内; 2.RequiredNew:当处于事务范围内的客户端应用调用组件商务方法时,EJB容器启动一个新的事务过程,组件商务方法执行在新事务过程范围内; 3.Mandatory:如果调用EJB组件商务方法的客户端应用不处于事务范围内,则EJB容器抛出TransactionRequiredException异常,强制客户端启动事务过程; 4.NotSupported:EJB组件的商务方法不需要运行在事务过程中。如果调用EJB组件方法的客户端应用处于事务过程中,则调用组件商务方法时原有事务过程挂起,直至组件方法运行结束; 5.Supports:组件方法必须处于事务范围内。如果调用组件商务方法的客户端不处于事务过程中,则EJB容器启动新的事务过程;6.Never:组件方法不需要运行在事务过程中。如果调用组件商务方法的客户端应用处于事务范围内,则EJB容器抛出RemoteException异常。 "
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值