POJ 3680 Intervals(经典费用流)

解题思路:

区间K覆盖问题:数轴上有一些带权值的区间,选出权和尽量大的一些区间,使得任意一个点最多被K个区间覆盖。

构图方法为:把每一个数作为一个节点,然后对于权值为W的区间[ u, v ]连一条边,容量为1,费用为-w,再对所有相邻

的点连边i -> i + 1,,容量为K,费用为0;最后求最左端到最右端的最小费用最大流即可。如果数值范围太大,需要先进行离散化。

#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <cmath>#define LL long long using namespace std;const int maxn = 500 + 10;const int INF = 0x3f3f3f3f;struct Edge{int from, to, cap, flow, cost;Edge(int u, int v, int c, int f, int w) : from(u), to(v), cap(c), flow(f), cost(w) { }};int n;vector<Edge>edges;vector<int>G[maxn];int inq[maxn];int d[maxn];int p[maxn];int a[maxn];void init(){for(int i=0;i<n;i++)G[i].clear();edges.clear();}void AddEdge(int from, int to, int cap, int cost){edges.push_back(Edge(from,to,cap,0,cost));edges.push_back(Edge(to,from,0,0,-cost));int M = edges.size();G[from].push_back(M-2);G[to].push_back(M-1);}bool SPFA(int s, int t, int& flow, LL& cost){for(int i=0;i<=n+1;i++) d[i] = INF;memset(inq, 0, sizeof(inq));d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;queue<int>Q;Q.push(s);while(!Q.empty()){int u = Q.front();Q.pop();inq[u] = 0;for(int i=0;i<G[u].size();i++){Edge& e = edges[G[u][i]];if(e.cap > e.flow && d[e.to] > d[u] + e.cost){d[e.to] = d[u] + e.cost;p[e.to] = G[u][i];a[e.to] = min(a[u], e.cap – e.flow);if(!inq[e.to]){Q.push(e.to);inq[e.to] = 1;}}}}if(d[t] == INF) return false;flow += a[t];cost += (LL) d[t] * (LL) a[t];for(int u=t;u!=s;u=edges[p[u]].from){edges[p[u]].flow += a[t];edges[p[u]^1].flow -= a[t];}return true;}int MincostMaxflow(int s, int t, LL& cost){int flow = 0; cost = 0;while(SPFA(s,t,flow,cost));return flow;}struct Node{int a;int p;bool operator < (const Node &rhs)const{return a < rhs.a;}}li[maxn];struct edge{int u, v,w;}ee[maxn];int main(){int T, N, K;scanf("%d", &T);while(T–){scanf("%d%d", &N, &K);int u, v, w;for(int i=1;i<=N;i++){scanf("%d%d%d", &u, &v, &w);li[2*i-1].a = u;li[2*i-1].p = -i;li[2*i].a = v;li[2*i].p= i;ee[i].u=u;ee[i].v=v;ee[i].w=w;}sort(li+1, li + 1 +2* N);int tmp = li[1].a,c = 1;for(int i=1;i<=2*N;i++){if(li[i].a != tmp){c++;tmp = li[i].a;}if(li[i].p > 0){ee[li[i].p].v = c;}elseee[-li[i].p].u = c;}n = c + 1;init();for(int i=0;i<c;i++)AddEdge(i,i+1,K,0);for(int i=1;i<=N;i++)AddEdge(ee[i].u,ee[i].v,1,-ee[i].w);LL cost = 0;int ans = MincostMaxflow(0,c,cost);printf("%lld\n",-cost);}return 0;}

悠然享受和大自然融合之乐。

POJ 3680 Intervals(经典费用流)

相关文章:

你感兴趣的文章:

标签云: