您的位置:首页 > 其它

uva 1317 - Concert Hall Scheduling(最小费用最大流)

2013-03-24 12:21 351 查看
You are appointed director of a famous concert hall, to save it from bankruptcy. The hall is very popular, and receives many requests to use its two fine rooms, but unfortunately the previous director was not very efficient, and it has been losing money
for many years. The two rooms are of the same size and arrangement. Therefore, each applicant wishing to hold a concert asks for a room without specifying which. Each room can be used for only one concert per day.

In order to make more money, you have decided to abandon the previous fixed price policy, and rather let applicants specify the price they are ready to pay. Each application shall specify a period[i,
j] and an asking price w, where
i and j are respectively the first and last days of the period
(1

i

j

365),
and w is a positive integer in yen, indicating the amount the applicant is willing to pay to use a room for the whole period.

You have received applications for the next year, and you should now choose the applications you will accept. Each application should be either accepted for its whole period or completely rejected. Each concert should use the same room during the whole applied
period.

Considering the dire economic situation of the concert hall, artistic quality is to be ignored, and you should just try to maximize the total income for the whole year by accepting the most profitable applications.

Input

The input has multiple data sets, each starting with a line consisting of a single integern, the number of applications in the data set. Then, it is followed byn lines, each of which represents
one application with a period[i, j] and an asking price
w yen in the following format.

i j w

A line containing a single zero indicates the end of the input.

The maximum number of applications in a data set is one thousand, and the maximum asking price is one million yen.

Output

For each data set, print a single line containing an integer, the maximum total income in yen for the data set.

Sample Input

4
1 2 10
2 3 10
3 3 10
1 3 10
6
1 20 1000
3 25 10000
5 15 5000
22 300 5500
10 295 9000
7 7 6000
8
32 251 2261
123 281 1339
211 235 5641
162 217 7273
22 139 7851
194 198 9190
119 274 878
122 173 8640
0


Sample Output

30
25500
38595


这道题是典型的:区间k覆盖问题。即数轴上有一些带权值的左闭右开区间,选出权和尽量大的一些区间,使得任意一个数最多被k个区间覆盖。

本题虽是闭区间,但可以转换成为左闭右开区间,然后建图方式如下:

把每个数作为一个结点,然后对于权值为w的区间[u,v),加边u->v,容量为1,费用为-w。再对所有相邻的点加边i->i+1,容量为k,费用为0。最后加上超级源点和汇点于最左右两边,然后求最小费用最大流即可。其中每个流量对应一组互不相交的区间。

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 367+10;
const int INF = 1000000000;

struct Edge{
    int from,to,cap,flow,cost;
};

struct MCMF {
  int n, m, s, t;
  vector<Edge> edges;
  vector<int> G[maxn];
  int inq[maxn];         // 是否在队列中
  int d[maxn];           // Bellman-Ford
  int p[maxn];           // 上一条弧
  int a[maxn];           // 可改进量

  void init(int n) {
    this->n = n;
    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});
    m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
  }

  bool BellmanFord(int s, int t, int &flow,int &cost) {
    for(int i = 0; i < n; 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;//s-t不连通,失败退出
    flow += a[t];
    cost += d[t] * a[t];
    int u = t;
    while(u != s) {
      edges[p[u]].flow += a[t];
      edges[p[u]^1].flow -= a[t];
      u = edges[p[u]].from;
    }
    return true;
  }

  // 需要保证初始网络中没有负权圈
  int Mincost(int s, int t) {
    int flow = 0,cost = 0;
    while(BellmanFord(s, t,flow, cost));
    return cost;
  }

};

MCMF g;

int main(){
    int n;
    while(scanf("%d",&n)){
        if(n == 0)  break;
        g.init(368);
        int sorce = 0,sink = 367;
        for(int i = 0;i < 367;i++)
            g.AddEdge(i,i+1,2,0);
        for(int i = 0;i < n;i++){
            int from,to,cost;
            scanf("%d%d%d",&from,&to,&cost);
            g.AddEdge(from,to+1,1,-cost);
        }
        printf("%d\n",-g.Mincost(sorce,sink));
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: