zoukankan      html  css  js  c++  java
  • 【PowerOJ1756&网络流24题】最长k可重区间集问题(费用流)

    题意:

     思路:

    【问题分析】

    最大权不相交路径问题,可以用最大费用最大流解决。

    【建模方法】

    方法1

    按左端点排序所有区间,把每个区间拆分看做两个顶点<i.a><i.b>,建立附加源S汇T,以及附加顶点S'。

    1、连接S到S'一条容量为K,费用为0的有向边。

    2、从S'到每个<i.a>连接一条容量为1,费用为0的有向边。

    3、从每个<i.b>到T连接一条容量为1,费用为0的有向边。

    4、从每个顶点<i.a>到<i.b>连接一条容量为1,费用为区间长度的有向边。

    5、对于每个区间i,与它右边的不相交的所有区间j各连一条容量为1,费用为0的有向边。

    求最大费用最大流,最大费用流值就是最长k可重区间集的长度。

    方法2

    离散化所有区间的端点,把每个端点看做一个顶点,建立附加源S汇T。

    1、从S到顶点1(最左边顶点)连接一条容量为K,费用为0的有向边。

    2、从顶点2N(最右边顶点)到T连接一条容量为K,费用为0的有向边。

    3、从顶点i到顶点i+1(i+1<=2N),连接一条容量为无穷大,费用为0的有向边。

    4、对于每个区间[a,b],从a对应的顶点i到b对应的顶点j连接一条容量为1,费用为区间长度的有向边。

    求最大费用最大流,最大费用流值就是最长k可重区间集的长度。

    【建模分析】

    这个问题可以看做是求K条权之和最大的不想交路径,每条路径为一些不相交的区间序列。由于是最大费用流,两条路径之间一定有一些区间相交,可以看做事相交部分重复了2次,而K条路经就是最多重

    复了K次。最简单的想法就是把区间排序后,不相交的区间之间连接一条边,由于每个区间只能用一次,所以要拆点,点内限制流量。如果我们改变一下思路,把端点作为网络中的顶点,区间恰恰是特定

    一些端点之间的边,这样建模的复杂度更小。方法1的边数是O(N^2)的,而方法2的边数是O(N)的,可以解决更大规模的问题。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef long double ld;
      7 typedef pair<int,int> PII;
      8 typedef pair<ll,ll> Pll;
      9 typedef vector<int> VI;
     10 typedef vector<PII> VII;
     11 typedef pair<ll,ll>P;
     12 #define N  50000
     13 #define M  1000000
     14 #define INF 1e9
     15 #define fi first
     16 #define se second
     17 #define MP make_pair
     18 #define pb push_back
     19 #define pi acos(-1)
     20 #define mem(a,b) memset(a,b,sizeof(a))
     21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     23 #define lowbit(x) x&(-x)
     24 #define Rand (rand()*(1<<16)+rand())
     25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     26 #define ls p<<1
     27 #define rs p<<1|1
     28 
     29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
     30       double eps=1e-6;
     31       int dx[4]={-1,1,0,0};
     32       int dy[4]={0,0,-1,1};
     33 
     34 struct node
     35 {
     36     int x,y;
     37 }a[N];
     38 
     39 int head[N],vet[N],nxt[N],len1[N],len2[N],dis[N],inq[N],q[N],pre[N][2],c[N],
     40     s,S,T,tot,ans1,ans2;
     41 
     42 int read()
     43 {
     44    int v=0,f=1;
     45    char c=getchar();
     46    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     47    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     48    return v*f;
     49 }
     50 
     51 void add(int a,int b,int c,int d)
     52 {
     53     nxt[++tot]=head[a];
     54     vet[tot]=b;
     55     len1[tot]=c;
     56     len2[tot]=d;
     57     head[a]=tot;
     58 
     59     nxt[++tot]=head[b];
     60     vet[tot]=a;
     61     len1[tot]=0;
     62     len2[tot]=-d;
     63     head[b]=tot;
     64 }
     65 
     66 int spfa()
     67 {
     68     rep(i,1,s)
     69     {
     70         dis[i]=-INF;
     71         inq[i]=0;
     72     }
     73     int t=0,w=1;
     74     q[1]=S; dis[S]=0; inq[S]=1;
     75     while(t<w)
     76     {
     77         t++; int u=q[t%(s+5)]; inq[u]=0;
     78         int e=head[u];
     79         while(e)
     80         {
     81             int v=vet[e];
     82             if(len1[e]&&dis[u]+len2[e]>dis[v])
     83             {
     84                 dis[v]=dis[u]+len2[e];
     85                 pre[v][0]=u;
     86                 pre[v][1]=e;
     87                 if(!inq[v])
     88                 {
     89                     w++; q[w%(s+5)]=v; inq[v]=1;
     90                 }
     91             }
     92             e=nxt[e];
     93         }
     94     }
     95     if(dis[T]==-INF) return 0;
     96     return 1;
     97 }
     98 
     99 void mcf()
    100 {
    101     int k=T,t=INF;
    102     while(k!=S)
    103     {
    104         int e=pre[k][1];
    105         t=min(t,len1[e]);
    106         k=pre[k][0];
    107     }
    108     ans1+=t;
    109     k=T;
    110     while(k!=S)
    111     {
    112         int e=pre[k][1];
    113         len1[e]-=t;
    114         len1[e^1]+=t;
    115         ans2+=t*len2[e];
    116         k=pre[k][0];
    117     }
    118 }
    119 
    120 int main()
    121 {
    122     //freopen("1.in","r",stdin);
    123     int n=read(),K=read();
    124     int m=0;
    125     rep(i,1,n)
    126     {
    127         a[i].x=read(),a[i].y=read();
    128         c[++m]=a[i].x;
    129         c[++m]=a[i].y;
    130     }
    131     sort(c+1,c+m+1);
    132     int k=unique(c+1,c+m+1)-c-1;
    133     s=k,S=++s,T=++s;
    134     rep(i,1,s) head[i]=0;
    135     tot=1;
    136     rep(i,1,n)
    137     {
    138         int len=a[i].y-a[i].x;
    139         a[i].x=lower_bound(c+1,c+k+1,a[i].x)-c;
    140         a[i].y=lower_bound(c+1,c+k+1,a[i].y)-c;
    141         add(a[i].x,a[i].y,1,len);
    142     }
    143     rep(i,1,k-1) add(i,i+1,K,0);
    144     add(S,1,K,0);
    145     add(k,T,K,0);
    146     ans1=ans2=0;
    147     while(spfa()) mcf();
    148     printf("%d
    ",ans2);
    149     return 0;
    150 
    151 }
  • 相关阅读:
    springboot 全局异常拦截器,友好异常提示
    java Word 转 PDF格式
    SpringCloud GateWay 使用 网关路由
    spring boot 读写参数到session
    springboot2.5.2 整合 flowable6.6.0 流程引擎
    java 自定义表单 动态表单 表单设计器 工作流引擎 flowable 项目源码
    springboot 运行 jar 包读取外部配置文件
    Spring Boot mybatisconfig 和 log4j 输出sql 日志
    SQL 数据查询语句之字符串拆分
    Enable Script debugging in IE8 at Window 7 operating system
  • 原文地址:https://www.cnblogs.com/myx12345/p/11766859.html
Copyright © 2011-2022 走看看