传说中的区间k覆盖问题。
给定n个带权开区间,选择其中一些使得区间权值之和最大,且所有区间内任意点被覆盖不能超过k次。
建图方法:
1.将区间离散化,对于离散化后的区间端点所对应的点i,i+1,加边(i,i+1,k,0)
2.对于每个区间(a,b),所对应离散化后的点(xx,yy),加边(xx,yy,-w,1),w为区间的权值
3.由源点src连一条到一个点的边(src,1,k,0),同理,由最后一个点t连一条道汇点sink的边(t,sink,k,0)
跑一遍最小费用了取反即为结果。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <queue> 5 #define maxn 410 6 #define maxm 2010 7 #define INF 1<<30 8 using namespace std; 9 struct MCMF{ 10 int src,sink,e,n; 11 int first[maxn]; 12 int cap[maxm],cost[maxm],v[maxm],next[maxm]; 13 bool flag; 14 void init(){ 15 e = 0; 16 memset(first,-1,sizeof(first)); 17 } 18 19 void add_edge(int a,int b,int cc,int ww){ 20 //printf("add:%d to %d,cap = %d,cost = %d ",a,b,cc,ww); 21 cap[e] = cc;cost[e] = ww;v[e] = b; 22 next[e] = first[a];first[a] = e++; 23 cap[e] = 0;cost[e] = -ww;v[e] = a; 24 next[e] = first[b];first[b] = e++; 25 } 26 27 int d[maxn],pre[maxn],pos[maxn]; 28 bool vis[maxn]; 29 30 bool spfa(int s,int t){ 31 memset(pre,-1,sizeof(pre)); 32 memset(vis,0,sizeof(vis)); 33 queue<int> Q; 34 for(int i = 0;i <= n;i++) d[i] = INF; 35 Q.push(s);pre[s] = s;d[s] = 0;vis[s] = 1; 36 while(!Q.empty()){ 37 int u = Q.front();Q.pop(); 38 vis[u] = 0; 39 for(int i = first[u];i != -1;i = next[i]){ 40 if(cap[i] > 0 && d[u] + cost[i] < d[v[i]]){ 41 d[v[i]] = d[u] + cost[i]; 42 pre[v[i]] = u;pos[v[i]] = i; 43 if(!vis[v[i]]) vis[v[i]] = 1,Q.push(v[i]); 44 } 45 } 46 } 47 return pre[t] != -1; 48 } 49 50 int Mincost; 51 int Maxflow; 52 53 int MinCostFlow(int s,int t,int nn){ 54 Mincost = 0,Maxflow = 0,n = nn; 55 while(spfa(s,t)){ 56 int min_f = INF; 57 for(int i = t;i != s;i = pre[i]) 58 if(cap[pos[i]] < min_f) min_f = cap[pos[i]]; 59 Mincost += d[t] * min_f; 60 Maxflow += min_f; 61 for(int i = t;i != s;i = pre[i]){ 62 cap[pos[i]] -= min_f; 63 cap[pos[i]^1] += min_f; 64 } 65 } 66 return Mincost; 67 } 68 }; 69 MCMF g; 70 71 struct Line{ 72 int a,b,w; 73 }line[210]; 74 int x[410]; 75 76 int main(){ 77 int T; 78 scanf("%d",&T); 79 while(T--){ 80 g.init(); 81 int N,K; 82 scanf("%d%d",&N,&K); 83 int cnt = 0; 84 for(int i = 0;i < N;i++){ 85 int a,b,w; 86 scanf("%d%d%d",&a,&b,&w); 87 x[cnt++] = a;x[cnt++] = b; 88 line[i].a = a;line[i].b = b;line[i].w = w; 89 } 90 sort(x,x+cnt); 91 int t = unique(x,x+cnt) - x; 92 //printf("t = %d ",t); 93 for(int i = 0;i < N;i++){ 94 int xx = lower_bound(x,x+t,line[i].a) - x + 1; 95 int yy = lower_bound(x,x+t,line[i].b) - x + 1; 96 g.add_edge(xx,yy,1,-line[i].w); 97 } 98 for(int i = 1;i < t;i++){ 99 g.add_edge(i,i+1,K,0); 100 } 101 int src = t+1,sink = src+1; 102 g.add_edge(src,1,K,0); 103 g.add_edge(t,sink,K,0); 104 int ans = g.MinCostFlow(src,sink,sink); 105 printf("%d ",-ans); 106 } 107 return 0; 108 }