給定實直線 L LL 上 n nn 個開區間組成的集合 I II,和一個正整數 k kk,試設計一個算法,從開區間集合 I II 中選取出開區間集合 S⊆I S \subseteq IS⊆I,使得在實直線 L LL 的任何一點 x xx,S SS 中包含點 x xx 的開區間個數不超過 k kk。且 ∑z∈S∣z∣ \sum\limits_{z \in S} | z |z∈S∑∣z∣ 達到最大。這樣的集合 S SS 稱爲開區間集合 I II 的最長 k kk 可重區間集。∑z∈S∣z∣ \sum\limits_{z \in S} | z |z∈S∑∣z∣ 稱爲最長 k kk 可重區間集的長度。html
對於給定的開區間集合 I II 和正整數 k kk,計算開區間集合 I II 的最長 k kk 可重區間集的長度。node
文件的第 1 11 行有 2 22 個正整數 n nn 和 k kk,分別表示開區間的個數和開區間的可重迭數。
接下來的 n nn 行,每行有 2 22 個整數 li l_ili 和 ri r_iri,表示開區間的左右端點座標,注意可能有 li>ri l_i > r_ili>ri,此時請將其交換。ios
輸出最長 k kk 可重區間集的長度。算法
4 2 1 7 6 8 7 10 9 13
15
1≤n≤500,1≤k≤3 1 \leq n \leq 500, 1 \leq k \leq 31≤n≤500,1≤k≤3網絡
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxn 1010 #define INF 1000000000 using namespace std; int n,k,mp[maxn],m,l[maxn],r[maxn],S,T,head[maxn],num=1,dis[maxn],ans; bool vis[maxn]; struct node{int to,pre,v,w;}e[200020]; void Insert(int from,int to,int v,int w){ e[++num].to=to;e[num].v=v;e[num].w=w;e[num].pre=head[from];head[from]=num; e[++num].to=from;e[num].v=0;e[num].w=-w;e[num].pre=head[to];head[to]=num; } int find(int x){return lower_bound(mp+1,mp+m+1,x)-mp;} void build(){ S=0;T=m+1; Insert(S,1,k,0);Insert(m,T,k,0); for(int i=1;i<m;i++)Insert(i,i+1,INF,0); for(int i=1;i<=n;i++)Insert(find(l[i]),find(r[i]),1,-r[i]+l[i]); } bool spfa(){ queue<int>q; memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); q.push(S);vis[S]=1;dis[S]=0; while(!q.empty()){ int now=q.front();q.pop();vis[now]=0; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(e[i].v>0&&dis[to]>dis[now]+e[i].w){ dis[to]=dis[now]+e[i].w; if(!vis[to]){vis[to]=1;q.push(to);} } } } return dis[T]<INF; } int dinic(int x,int flow){ if(x==T||flow==0)return flow; int rest=flow;vis[x]=1; for(int i=head[x];i;i=e[i].pre){ int to=e[i].to; if(dis[to]==dis[x]+e[i].w&&e[i].v>0&&!vis[to]){ int delta=dinic(to,min(rest,e[i].v)); e[i].v-=delta; e[i^1].v+=delta; rest-=delta; ans+=e[i].w*delta; } } vis[x]=0; return flow-rest; } void work(){ while(spfa()){ memset(vis,0,sizeof(vis)); dinic(S,INF); } } int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d%d",&l[i],&r[i]); if(l[i]>r[i])swap(l[i],r[i]); mp[++m]=l[i];mp[++m]=r[i]; } sort(mp+1,mp+m+1); m=unique(mp+1,mp+m+1)-mp-1; build(); work(); ans=-ans; printf("%d",ans); }