您的位置:首页 > 理论基础 > 计算机网络

HDU 3572 Task Schedule 网络流 ISAP

2013-09-05 11:07 239 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3572

题意:

  给出N个任务,M个机器,每天每台机器只能处理一件事,接下来N行,每行有p s e

分别表示这个任务要用p天,要在s~e天完成,问你这所有任务能不能完成。

坑爹:

  模板题,注意一下vector数组clear的时候控制好长度,有可能会超时。

解法:

  将N个任务标号为1~N,用个max_Day来找最大的天数,然后天数的标号为

N+1~max_Day+N , 建立一个源点0,汇点max_Day+N+1。

建图的步骤:先将所有任务与源点相连,权值为完成所需天数,再将这个任务与再这个任务范围

内的时间(天)相连,权值为1,最后将每个时间与汇点相连,权值为M,因为只有M个机器。

#include<iostream>
#include<stdio.h>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 500000 + 10;
const int INF = 0x3fffffff;

struct Edge {
int from;
int to;
int cap;
int flow;
}edge[2*maxn];
vector<int> G[maxn];
int head[maxn];
int cur[maxn];
bool used[maxn];
int deep[maxn];
int front[maxn];
int gap[maxn];
int cnt;
int N;
int M;

void addEdge(int from, int to, int cap)
{
edge[cnt].from = from;
edge[cnt].to = to;
edge[cnt].cap = cap;
edge[cnt].flow = 0;
cnt ++;

edge[cnt].from = to;
edge[cnt].to = from;
edge[cnt].cap = 0;
edge[cnt].flow = 0;
cnt ++;

G[from].push_back(cnt-2);
G[to].push_back(cnt-1);
}

bool BFS(int s, int t)
{
memset(used,0,sizeof(used));
queue<int> Q;
Q.push(t);
deep[t] = 0;
used[t] = true;
while(!Q.empty())
{
int top = Q.front();
Q.pop();
int i;
for(i=0; i<G[top].size(); i++)
{
Edge e = edge[G[top][i]];
if(!used[e.to])
{
used[e.to] = true;
deep[e.to] = deep[top] + 1;
Q.push(e.to);
}
}
}
return used[s];
}

int Augment(int s,int t)
{
int begin = t;
int minFlow = INF;
while(begin != s)
{
Edge& e = edge[front[begin]];
minFlow = min(minFlow, e.cap-e.flow);
begin = edge[front[begin]].from;
}
begin = t;
while(begin != s)
{
edge[front[begin]].flow += minFlow;
edge[front[begin]^1].flow -= minFlow;
begin = edge[front[begin]].from;
}
return minFlow;
}

int Maxflow(int s,int t)
{
int flow = 0;
BFS(s,t);
memset(gap,0,sizeof(gap));
memset(cur,0,sizeof(cur));
int i;
for(i=0; i<=N; i++)
{
gap[deep[i]] ++;
}
int begin = s;
while(deep[s] < N)
{
if(begin == t)
{
flow += Augment(s,t);
begin = s;
}
bool ok = false;
int i;
for(i=cur[begin]; i<G[begin].size(); i++)
{
Edge& e = edge[G[begin][i]];
if(e.cap > e.flow && deep[begin] == deep[e.to] + 1)
{
ok = true;
front[e.to] = G[begin][i];
cur[begin] = i;
begin = e.to;
break;
}
}
if(!ok)
{
int m = N - 1;
int i;
for(i=0; i<G[begin].size(); i++)
{
Edge& e = edge[G[begin][i]];
if(e.cap > e.flow)
{
m = min(m, deep[e.to]);
}
}
if(--gap[deep[begin]] == 0)
{
break;
}
gap[deep[begin] = m+1] ++;
cur[begin] = 0;
if(begin != s)
{
begin = edge[front[begin]].from;
}
}
}
return flow;
}

int main()
{
int T;
scanf("%d",&T);
int Case;
int machine;
int s = 0;
int t = 0;
for(Case=1; Case<=T; Case++)
{
scanf("%d%d",&M,&machine);//M 任务数量 ,machine 机器数量
int i;
for(i=0; i<=t; i++)
{
G[i].clear();
}
cnt = 0;
int max_Day = 0;
memset(deep,0,sizeof(deep));
int sum_Task = 0;
for(i=1; i<=M; i++)
{
int p;
int s;
int e;
scanf("%d%d%d",&p,&s,&e);
sum_Task += p;
if(e > max_Day)
{
max_Day = e;
}
addEdge(0,i,p);
int j;
for(j=s+M; j<=e+M; j++)
{
addEdge(i,j,1);
}
}
s = 0;//源点
t = max_Day+M+1;//汇点
N = t;
for(i=M+1; i<=max_Day+M; i++)
{
addEdge(i,t,machine);
}
int flow = Maxflow(s,t);
if(sum_Task == flow)
{
printf("Case %d: Yes\n\n",Case);
}
else
{
printf("Case %d: No\n\n",Case);
}
}
//system("pause");
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: