HDU3572构造图的模型
第一次面对建模的图,也映照了我以前想的算法不是重点,问题的转化才是重点
Description:
N个任务,M台机器,对于每一个任务有p,s,e表示该任务要做p个时长,要从[s,……)开始,从(……e]结束,问你这些任务最后能完成吗Yes || No
Solution:
做的是最大流专辑,知道是最大流的题目,但是就是不知道怎么转化为最大流的问题。。。
Yes or No的关键就是最大流能否等于任务总时长,面对这个题,对于每一个任务 i ,从源点到i添加一条边,边的权值(容量)是对应任务的p,如果yes是不是从s流出的量 fmax == sum(p),假设这些流量流到了任务,那么任务如何处理呢,就是看看时间段如何分配,因为可以任意时间段开始,暂停直到结束所以每个任务与它对应的每一个时间段都要添加一个1(容量),不管这个任务咋分配,只要能分配给它的p就行了,那分配好时间段了呢,是不是还有一个条件也就是机器数目,同一个时间最多m个机器工作,所以每一个时间段,都要向汇点T,传入一个m的容量,表示的意义也很明显啦,最后求出最大流就好了!真舒服,第一次懂一类题的感觉应该都是这样的吧略略略
要注意一下,最多有多少边哈·
#include <iostream>
#include <cstdio>
#include <string.h>
#include <queue>
#include <cmath>
#include <algorithm>
#define inf (1 << 28)
using namespace std;
typedef long long ll;
const int maxn = 5000;
const int maxm = 251000+7;
int n,m;
int S,T;
struct node{
int pre;
int to,cost;
}e[maxm<<1];
int id[maxn],cnt;
int flor[maxn];
int cur[maxn];//DFS的优化遍历
void add(int from,int to,int cost)
{
e[cnt].to = to;
e[cnt].cost = cost;
e[cnt].pre = id[from];
id[from] = cnt++;
swap(from,to);
e[cnt].to = to;
e[cnt].cost = 0;
e[cnt].pre = id[from];
id[from] = cnt++;
}
int bfs(int s,int t)
{
memset(flor,0,sizeof(flor));
queue < int > q;
while(q.size())q.pop();
flor[s] = 1;
q.push(s);
while(q.size())
{
int now = q.front();
q.pop();
for(int i = id[now];~i;i=e[i].pre)
{
int to = e[i].to;
int cost = e[i].cost;
if(flor[to] == 0 && cost > 0)
{
flor[to] = flor[now] + 1;
q.push(to);
if(to == t)return 1;
}
}
}
return 0;
}
int dfs(int s,int t,int value)
{
//ret表示目前流到s的最大流量,用来计算回溯的时候是否还有可行流
int ret = value;
if(s == t || value == 0)return value;
int a;
for(int &i = cur[s];~i;i = e[i].pre)
{
int to = e[i].to;
int cost = e[i].cost;
if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,cost))))
{
e[i].cost -= a;
e[i^1].cost += a;
ret -= a;
if(ret == 0)break;
}
}
//s点后面没有可行的流了
if(ret == value) flor[s] = 0;
return value - ret;
}
int dinic(int s,int t)
{
ll ret = 0;
while(bfs(s,t))
{
memcpy(cur,id,sizeof(id));
ret += dfs(s,t,inf);
}
return ret;
}
void init()
{
memset(id,-1,sizeof(id));
cnt = 0;
}
int main()
{
int t;
scanf("%d",&t);
int cas = 0;
while(t--)
{
scanf("%d%d",&n,&m);
init();
int p,s,e;
int tl = -1,tr = -1;
S = 0;
int sump = 0;
for(int i = 1;i <= n;++i)
{
scanf("%d%d%d",&p,&s,&e);
sump += p;
add(S,i,p);
if(tl == -1)tl = s;
if(tr == -1)tr = e;
tl = min(tl,s);
tr = max(tr,e);
for(int j = s;j <= e;++j)
{
add(i,n+j,1);
}
}
T = n + tr + 1;
for(int i = tl;i <= tr;++i)
{
add(n + i,T,m);
}
ll ret = dinic(S,T);
printf("Case %d: %s\n\n",++cas,ret == sump ? "Yes" : "No");
}
return 0;
}

浙公网安备 33010602011771号