【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\n",ans2);
149     return 0;
150 
151 }

猜你喜欢

转载自www.cnblogs.com/myx12345/p/11766859.html