2019.4.9 一题——概率期望+0/1分数规划+最大权闭合子图

  没注意 “第 x 条边和第 y 条边的起点是相同的” 的限制。没想出来。

  有这个限制,可以考虑每个点分别计算。令 \( f[i] \) 表示从 i 出发的最大边数期望,那么先把拓扑序在自己之后的点的 \( f[ ] \) 算出来,然后考虑自己这个点的出边怎么做能使自己的 \( f[ ] \) 最大。

  \( f[i]=\frac{ \sum f[j]+1 }{ d } \) ,其中 d 是保留下来的边数, j 是保留边指向的点。

  如果把 \( f[ ]+1 \) 看做收益, 1 看做代价,那么这个式子就是 0/1 分数规划。考虑二分找出最优比率。

  已有二分值,每条出边的权值就确定了。考虑选一个权值和最大的出边集合。限制条件意为选了 x 必须选 y ,所以这是一个最大权闭合子图的问题。用最小割求解即可。(不用把成环的限制缩点!)

  注意每次网络流之后要把 hd 和 cap 都赋回原值。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define db double
#define pb push_back
using namespace std;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)fx=0;ch=getchar();}
  while(ch>=‘0‘&&ch<=‘9‘)ret=ret*10+ch-‘0‘,ch=getchar();
  return fx?ret:-ret;
}
const int N=55,M=505,K=2005;
int n,m,k,hd[N],xnt,to[M],nxt[M];
int rd[N],q[N]; db f[N];
db c[M]; bool chk[M];
void add(int x,int y)
{
  to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;
}
namespace G{
  const int M2=(K+M)*2;
  const db eps=1e-8,jmp=1e-4,INF=3000;
  int en,hd[M],xnt=1,to[M2],nxt[M2]; db cap[M2];
  int cur[M],yhd[M]; db ycap[M2];
  int dfn[M],q[M];
  vector<int> vt;
  int dcmp(db x)
  {
    if(x>eps)return 1;else if(x<-eps)return -1; return 0;
  }
  void add(int x,int y,db z)
  {
    to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;cap[xnt]=z;
    to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;cap[xnt]=0;
  }
  void init()
  {
    for(int i=1,u,v;i<=k;i++)
      {
    u=rdn();v=rdn();add(u,v,INF);
      }
    en=m+1;
  }
  bool bfs()
  {
    memset(dfn,0,sizeof dfn); dfn[0]=1;
    int he=0, tl=0; q[++tl]=0;
    while(he<tl)
      {
    int k=q[++he];
    for(int i=hd[k],v;i;i=nxt[i])
      {
        if(dcmp(cap[i])>0&&!dfn[v=to[i]])
          {
        dfn[v]=dfn[k]+1; q[++tl]=v;
          }
      }
      }
    return dfn[en];
  }
  db dinic(int cr,db flow)
  {
    if(cr==en)return flow;
    db use=0;
    for(int &i=cur[cr],v;i;i=nxt[i])
      if(dcmp(cap[i])>0&&dfn[v=to[i]]==dfn[cr]+1)
    {
      db tmp=dinic(v,min(flow-use,cap[i]));
      if(dcmp(tmp)==0){dfn[v]=0;continue;}
      use+=tmp; cap[i]-=tmp; cap[i^1]+=tmp;
      if(dcmp(flow-use)==0)return use;
    }
    return use;
  }
  db solve()
  {
    db l=0,r=n,ans=0;
    vt.clear();//
    for(int i=1;i<=m;i++) if(chk[i]) vt.pb(i);
    memcpy(yhd,hd,sizeof hd);
    memcpy(ycap,cap,sizeof cap);
    int yxnt=xnt;
    while(r-l>jmp)
      {
    db mid=(l+r)/2, sm=0;
    memcpy(hd,yhd,sizeof yhd);
    memcpy(cap,ycap,sizeof ycap);
    xnt=yxnt;
    for(int i=0,lm=vt.size();i<lm;i++)
      {
        int cr=vt[i]; db tp=c[cr]-mid;
        if(dcmp(tp)>0)
          {
        sm+=tp; add(0,cr,tp);
          }
        else if(dcmp(tp)<0)
          {
        add(cr,en,-tp);
          }
      }
    while(bfs())
      {
        memcpy(cur,hd,sizeof hd);
        sm-=dinic(0,INF);
      }
    if(dcmp(sm)>0)ans=mid,l=mid+jmp;
    else r=mid-jmp;
      }
    memcpy(hd,yhd,sizeof yhd);/////
    memcpy(cap,ycap,sizeof ycap);
    return ans;
  }
}
int main()
{
  n=rdn();m=rdn();k=rdn();
  for(int i=1,u,v;i<=m;i++)
    {
      u=rdn();v=rdn();add(u,v);rd[v]++;
    }
  G::init();
  int he=0, tl=0;
  for(int i=1;i<=n;i++)
    if(!rd[i])q[++tl]=i;
  while(he<tl)
    {
      int k=q[++he];
      for(int i=hd[k],v;i;i=nxt[i])
    if((--rd[v=to[i]])==0)q[++tl]=v;
    }
  for(int i=n;i;i--)
    {
      int cr=q[i];
      for(int i=hd[cr];i;i=nxt[i])
    {
      c[i]=f[to[i]]+1;
      chk[i]=1;
    }
      f[cr]=G::solve();
      for(int i=hd[cr];i;i=nxt[i])
    {
      chk[i]=0;
    }
    }
  printf("%.10f\n",f[1]);
  return 0;
}

原文地址:https://www.cnblogs.com/Narh/p/10682395.html

时间: 2024-10-03 13:41:19

2019.4.9 一题——概率期望+0/1分数规划+最大权闭合子图的相关文章

POJ - 2976 Dropping tests &amp;&amp; 0/1 分数规划

POJ - 2976 Dropping tests 你有 \(n\) 次考试成绩, 定义考试平均成绩为 \[\frac{\sum_{i = 1}^{n} a_{i}}{\sum_{i = 1}^{n} b_{i}}\] 你可以考虑放弃 \(K\) 次成绩, 求最大平均成绩 * 100 小插曲: 被精度卡成喜羊羊 0/1分数规划\(from\)人生导师 Solution 01分数规划(不是很)裸题, 在每次 \(check\) 时, 选取较大的 \(num - K + 1\) 次即可 Code #

[网络流24题] 太空飞行计划 (最大权闭合子图---网络最大流)

727. [网络流24题] 太空飞行计划 ★★☆ 输入文件:shuttle.in 输出文件:shuttle.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={ I1, I2,…,In }.实验Ej 需要用到的仪器是I的子集Rj∈I.配置仪器Ik 的费用为ck 美元.实验Ej

『0/1分数规划 二分法』

0/1分数规划 模型 0/1分数规划指的是这样一个问题模型: 给定整数\(a_1,a_2,...,a_n\)和\(b_1,b_2,...,b_n\),求一组解\(x_1,x_2,...,x_n(\forall\ i\in[1,n],x_i=1,0)\),使得下式最大化:\[\frac{\sum_{i=1}^na_i*x_i}{\sum_{i=1}^nb_i*x_i}\] 简单地说,就是给定\(n\)对整数\(a_i,b_i\),从中选取若干对,使得选出的\(a\)之和与\(b\)之和的比值最大.

[例题/总结]0/1分数规划

[TOC] ##一.总述 0/1分数规划是专门解决0/1分数规划模型的一种算法~~(废话)~~.所以说0/1分数规划模型是什么呢?给定整数{\(a_1,a_2,a_3,...,a_n\)},{\(b_1,b_2,b_3,...,b_n\)}从中选出若干对数,使得它们各自和的比值最大.公式如下: \(\frac{\sum_{p=1}^{n}a_p\times x_p}{\sum_{p=1}^{n}b_p\times x_p}(x_p=1,0)\) ##二.实现原理 那么我们用什么方法可以求出这样一

刷题总结——太空飞行计划(最大权闭合子图用最大流解决)

题目: 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 E={E1,E2,-,Em},和进行这些实验需要使用的全部仪器的集合 I={I1, I2,-In}. 实验 Ej 需要用到的仪器是 I 的子集 Rj∈I.配置仪器 Ik 的费用为 Ck 美元.实验 Ej 的赞助商已同意为该实验结果支付 Pj 美元.W 教授的任务是找出一个有效算法, 确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的

bzoj 3232 圈地游戏——0/1分数规划(或网络流)

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3232 当然是0/1分数规划.但加的东西和减的东西不在一起,怎么办? 考虑把它们合在一起.因为边围成的形状像一个环,所以把格子的贡献也放到边上,然后正常判环. 放到边上的方法就是:比如竖着的边,可以在每一行上维护该行格子值前缀和,然后指定那个围成的形状是,比如,逆时针的,那么向上的边就加上到它为止的前缀值,向下的边就减去到它为止的前缀值,然后就能判环了! 这样一定只有一个环.但多个环答案不会

0/1分数规划

学习了lyd书上的0/1分数规划,发现这类题目都有一个特点,就是求$\frac{\sum_{a_{i}*x_{i}}}{\sum_{b_{i}*x_{i}}}$的最大或者最小,再加一些限制取不取的条件. POJ2976 二分答案+sort取前(n-k+1)个. #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; con

Yougth的最大化(好题,二分查找 0 1分数规划)

Yougth的最大化 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 Yougth现在有n个物品的重量和价值分别是Wi和Vi,你能帮他从中选出k个物品使得单位重量的价值最大吗? 输入 有多组测试数据每组测试数据第一行有两个数n和k,接下来一行有n个数Wi和Vi.(1<=k=n<=10000) (1<=Wi,Vi<=1000000) 输出 输出使得单位价值的最大值.(保留两位小数) 样例输入 3 2 2 2 5 3 2 1 样例输出 0.75 1 #in

POJ 3621(0/1分数规划,二分) Sightseeing Cows

题意 给一个n个点m条边的图,每一个点和每一条边都有权值.现在要找一个环的点权和/边权和最大,求这个最大值. 思路 SPFA+二分 题目的关系式:点权和/边权和 <= ans 转换一下就变成 ans*边权和 - 点权和 >= 0; 二分答案,然后用SPFA去check是否存在一个负权回路. 参考code: /* #pragma warning (disable: 4786) #pragma comment (linker, "/STACK:0x800000") */ #in