Machine Programming
题目连接:
http://codeforces.com/problemset/problem/164/B
Descriptionww.co
One remarkable day company "X" received k machines. And they were not simple machines, they were mechanical programmers! This was the last unsuccessful step before switching to android programmers, but that's another story.
The company has now n tasks, for each of them we know the start time of its execution si, the duration of its execution ti, and the company profit from its completion ci. Any machine can perform any task, exactly one at a time. If a machine has started to perform the task, it is busy at all moments of time from si to si + ti - 1, inclusive, and it cannot switch to another task.
You are required to select a set of tasks which can be done with these k machines, and which will bring the maximum total profit.
Input
The first line contains two integer numbers n and k (1 ≤ n ≤ 1000, 1 ≤ k ≤ 50) — the numbers of tasks and machines, correspondingly.
The next n lines contain space-separated groups of three integers si, ti, ci (1 ≤ si, ti ≤ 109, 1 ≤ ci ≤ 106), si is the time where they start executing the i-th task, ti is the duration of the i-th task and ci is the profit of its execution.
Output
Print n integers x1, x2, ..., xn. Number xi should equal 1, if task i should be completed and otherwise it should equal 0.
If there are several optimal solutions, print any of them.
Sample Input
3 1
2 7 5
1 3 3
4 1 3
Sample Output
0 1 1
Hint
题意
有n个任务,m个机器,每个机器同一时间只能处理一个任务
每个任务开始时间为s,持续时间为t,做完可以赚c元
问你做哪几个任务可以拿到最多的钱
输出方案
题解:
费用流
离散化每个任务的开始时间和结束时间,然后建图跑一遍就好了
把所有时间扔到一个队列里面排序
然后建立源点到最开始任务的起始时间-第二个时间-第三个时间-....-最后一个时间点-汇点,期间流量都是m,花费为0
然后对于每一个任务,连一条开始时间到结束时间+1的边,花费为-c,流量为1的
然后这样跑费用流一定就是答案了
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10000;
const int MAXM = 100000;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to, next, cap, flow, cost;
int id;
int x, y;
} edge[MAXM],HH[MAXN],MM[MAXN];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int N, M;
void init()
{
N = MAXN;
tol = 0;
memset(head, -1, sizeof(head));
}
int addedge(int u, int v, int cap, int cost, int id)//左端点,右端点,容量,花费
{
edge[tol]. to = v;
edge[tol]. cap = cap;
edge[tol]. cost = cost;
edge[tol]. flow = 0;
edge[tol]. next = head[u];
edge[tol]. id = id;
int t = tol;
head[u] = tol++;
edge[tol]. to = u;
edge[tol]. cap = 0;
edge[tol]. cost = -cost;
edge[tol]. flow = 0;
edge[tol]. next = head[v];
edge[tol]. id = id;
head[v] = tol++;
return tol;
}
bool spfa(int s, int t)
{
queue<int>q;
for(int i = 0; i < N; i++)
{
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[s] = 0;
vis[s] = true;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = false;
for(int i = head[u]; i != -1; i = edge[i]. next)
{
int v = edge[i]. to;
if(edge[i]. cap > edge[i]. flow &&
dis[v] > dis[u] + edge[i]. cost )
{
dis[v] = dis[u] + edge[i]. cost;
pre[v] = i;
if(!vis[v])
{
vis[v] = true;
q.push(v);
}
}
}
}
if(pre[t] == -1) return false;
else return true;
}
//返回的是最大流, cost存的是最小费用
int minCostMaxflow(int s, int t, int &cost)
{
int flow = 0;
cost = 0;
while(spfa(s,t))
{
int Min = INF;
for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
{
if(Min > edge[i]. cap - edge[i]. flow)
Min = edge[i]. cap - edge[i]. flow;
}
for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
{
edge[i]. flow += Min;
edge[i^1]. flow -= Min;
cost += edge[i]. cost * Min;
}
flow += Min;
}
return flow;
}
struct node
{
int st,et,ct;
int id;
}task[MAXN];
bool cmp(node A,node B)
{
if(A.st==B.st)return A.et<B.et;
return A.st<B.st;
}
map<int,int> H;
vector<int> V;
int id[3000];
int main()
{
int n, m;
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&task[i].st,&task[i].et,&task[i].ct);
task[i].et+=task[i].st-1;
task[i].id=i;
V.push_back(task[i].st);
V.push_back(task[i].et);
}
sort(V.begin(),V.end());
V.erase(unique(V.begin(),V.end()),V.end());
for(int i=0;i<V.size();i++)
H[V[i]]=i+1;
for(int i=1;i<=V.size();i++)
addedge(i-1,i,m,0,0);
addedge(V.size(),V.size()+1,m,0,0);
addedge(V.size()+1,V.size()+2,m,0,0);
for(int i=1;i<=n;i++)
id[i]=addedge(H[task[i].st],H[task[i].et]+1,1,-task[i].ct,i);
int ans1=0,ans2=0;
ans1=minCostMaxflow(0,V.size()+2,ans2);
//printf("%d
",ans2);
for(int i=1;i<=n;i++)
printf("%d ",edge[id[i]-2].flow);
return 0;
}