题意:
思路:
【问题分析】
最大权不相交路径问题,可以用最大费用最大流解决。
【建模方法】
方法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 }