HDU 3572 最大流
【题意】有n个任务,每个任务必须开始于第Si天之后(包括Si),结束于第Ei天之前(包括Ei),每个任务持续的时间为Pi,现在有m台机器,每台每天只能专注做其中一件任务,每个任务做的时间可以不连续。问是否存在一种方案使得这n个任务顺利完成
【类型】最大流
【建图】设一个源点S,将每个任务分别化成一个点,S向每个任务连一条边,容量为Pi,接着每个任务向时间Si~Ei分别连一条容量为1的边,每个时间向汇点连一条容量为m的边。这样跑最大流即可。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 10005
#define MAXM 1000005
#define INF 0x3fffffff
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,ans,big,cas,num,w,t,u,v,p,s,e,S,F,sum,max_time;
bool flag; struct Edge{
int u,v,weight;
int next;
}edge[MAXM];
int head[MAXN]; /* head[u]表示顶点u第一条邻接边的序号, 若head[u] = -1, u没有邻接边 */
int current; /* 当前有多少条边 */ void add_edge(int u, int v, int weight)
{
/* 添加正向边u->v */
edge[current].u = u;
edge[current].v = v;
edge[current].weight = weight;
edge[current].next = head[u];
head[u] = current++;
/* 添加反向边v->u */
edge[current].u = v;
edge[current].v = u;
edge[current].weight = 0;
edge[current].next = head[v];
head[v] = current++;
} int isap(int s, int e , int n)
{
int i,u,v,max_flow,aug,min_lev; /* 寻找增广路径的过程中, curedge[u]保存的是对于顶点u当前遍历的边, 寻找顶点u的邻接边时不用每次
* 都从head[u]开始找, 而是从curedge[u]开始找, 这样就减少了搜索次数
* 当增广路径找到后
* curedge保存的就是一条增广路径了, 比如
* 0---四-->1---六-->2--七--->3---八--->4 0,1,2,3,4是顶点号, 四六七八是边的序号
* curedge[0] = 四, curedge[1] = 六, ... curedge[3] = 8, curedge[i]即保存找过的轨迹
*/
int curedge[MAXN],parent[MAXN],level[MAXN]; /* count[l]表示对于属于层次l的顶点个数, 如果某个层次没有顶点了,
* 就出现断层, 意味着没有增广路径了, 这就是gap优化, 可以提前结束寻找过程
* augment[v]表示从源点到顶点v中允许的最大流量, 即这条路线的最小权重
*/
int count[MAXN],augment[MAXN]; memset(level,0,sizeof(level));
memset(count,0,sizeof(count));
//初始时每个顶点都从第一条边开始找
for (i=0;i<=n;i++)
{
curedge[i] = head[i];
}
max_flow=0;
augment[s]=INF;
parent[s]=-1;
u=s; while (level[s]<n) /* 不能写成level[s] < MAX_INT */
{
if (u==e) /* 找到一条增广路径 */
{
max_flow+=augment[e];
aug=augment[e];
//debug("找到一条增广路径, augment = %d\n", aug);
//debug("%d", e);
for (v=parent[e];v!=-1;v=parent[v]) /* 从后往前遍历路径 */
{
i=curedge[v];
//debug("<--%d", v);
edge[i].weight-=aug;
edge[i^1].weight+=aug; /* 如果i是偶数, i^1 = i+1, 如果i是奇数, i^1 = i-1 */
augment[edge[i].v]-=aug;
if (edge[i].weight==0) u=v; /* u指向增广后最后可达的顶点, 下次就从它继续找 */
}
//debug("\n");
}
/* 从顶点u往下找邻接点 */
for (i=curedge[u];i!=-1;i=edge[i].next) /* 从curedge[u]开始找, 而不是head[u]从头开始, curedge[u]保存的是上次找过的边 */
{
v=edge[i].v;
if (edge[i].weight>0 && level[u]==(level[v]+1)) /* 找到一条边就停止 */
{
augment[v]=min(augment[u],edge[i].weight);
curedge[u]=i;
parent[v]=u;
u=v;
break;
}
}
if (i==-1) /* 没有邻接点, 回溯到上一个点 */
{
if (--count[level[u]]==0)
{
//debug("顶点%d在level %d断层\n", u, level[u]);//GAP优化
break;
}
curedge[u]=head[u]; /* 顶点u的所有边都试过了,没有出路, 更新了u的level后, 又从第一条边开始找 */
//找出level最小的邻接点
min_lev=n;
for (i=head[u];i!=-1;i=edge[i].next)
{
if (edge[i].weight>0)
{
min_lev=min(level[edge[i].v],min_lev);
}
}
level[u]=min_lev+1;
count[level[u]]++;
//debug("顶点%d的level= %d\n", u, level[u]);
//debug("顶点%d走不通, 回到%d\n", u, edge[curedge[u]].u);
if (u!=s) u=parent[u]; /* 回退到上一个顶点 */
}
}
return max_flow;
} int main()
{
scanf("%d",&T);
for (cas=1;cas<=T;cas++)
{
memset(head,-1,sizeof(head));current=0;
scanf("%d%d",&n,&m);
S=0;sum=0;
max_time=0;
for (i=1;i<=n;i++)
{
scanf("%d%d%d",&p,&s,&e);
sum+=p;
max_time=max(max_time,e);
add_edge(S,i,p);
for (j=s;j<=e;j++)
{
add_edge(i,n+j,1);
}
}
F=n+max_time+1;
for (i=1;i<=max_time;i++)
{
add_edge(n+i,F,m);
}
if (isap(S,F,F)==sum) printf("Case %d: Yes\n\n",cas);
else printf("Case %d: No\n\n",cas);
}
return 0;
}
HDU 3572 最大流的更多相关文章
- hdu 3572 最大流判断满流
#include<stdio.h> #include<string.h> #include<queue> using namespace std; #define ...
- HDU 3572 Task Schedule(拆点+最大流dinic)
Task Schedule Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- HDU 3572 Task Schedule (最大流)
C - Task Schedule Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u S ...
- HDU 1532 最大流入门
1.HDU 1532 最大流入门,n个n条边,求第1点到第m点的最大流.只用EK做了一下. #include<bits/stdc++.h> using namespace std; #pr ...
- hdu 3572 Task Schedule(最大流)2010 ACM-ICPC Multi-University Training Contest(13)——Host by UESTC
题意: 告诉我们有m个任务和k个机器.第i个任务需要ci天完成,最早从第ai天开始,最晚在第bi天结束.每台机器每天可以执行一个任务.问,是否可以将所有的任务都按时完成? 输入: 首行输入一个整数t, ...
- HDU 3572 Task Schedule(最大流判断满流)
https://vjudge.net/problem/HDU-3572 题意: 有N个作业和M台机器,每个作业都有一个持续时间P,工作的日期为S~E.作业可以断断续续的在不同机器上做,每台机器每次只可 ...
- hdu 3572(构图+最大流)
Task Schedule Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- hdu 3572 Task Schedule(最大流&&建图经典&&dinic)
Task Schedule Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- hdu 3572 Task Schedule【 最大流 】
求出最大流,再判断是否满流 先不理解为什么要这样建图 后来看了这一篇题解 http://blog.csdn.net/u012350533/article/details/12361003 把0看做源点 ...
随机推荐
- python challenge 16
前情回顾:上一篇 第16关地址 打开16关,又是一张奇奇怪怪很多点点的图片,应该又是与PIL库有关的. 页面的标题是:let me get this straight.这是英语中的一句俚语,意思是让我 ...
- uvalive 5760 Alice and Bob (组合游戏,dp)
题目链接: http://vjudge.net/problem/viewProblem.action?id=25636 对于>1的堆,必然会被其中一人全部合并. 然后就是二维dp,dp[非1堆的 ...
- uva 11673 Garbage Remembering Exam (概率)
题目链接: http://vjudge.net/problem/viewProblem.action?id=42000 该过程为随即过程,因此总期望值等于个单词对应的期望值,即它们wasted的概率 ...
- [转自已]Windos多个文件快速重命名说明+图解
转自己以前的文章,给新博客带点气氛. 1.(复制的)比如在文件夹中包含yin.jpg.ye.jpg.zou.jpg三个文件,你希望将它们命名为"photo+数字"的文件名形式,那么 ...
- 初涉JavaScript模式 (8) : 函数 【概述】
什么是函数 函数,是一个大型程序中的某部份代码,由一个或多个语句块组成.它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性.(维基百科) 函数的特点 第一类对象 在JavaScript世界中 ...
- c# sqlserver备份还原(转)
WinForm c# 备份 还原 数据库 其实是个非常简单的问题,一个Form,一个Button,一个OpenFileDialog,一个SaveFileDialog.下面给出备份与还原类 using ...
- C语言的算法--------二分法查找
int find(int n,int a[],int l){int low=0;int high=l-1;int middle=0;while(low<high){middle=(low+hig ...
- 如何修正Feedly文章中文標題亂碼或無法正常顯示的問題
在7月1日Google關閉Reader之前,我想應該有許多人都已經從Google Reader移到其他服務上了,其中受益最大的者莫過於Feedly了,一下子就吸收了幾百萬的用戶,而我也是其中之一,由於 ...
- Configure swagger with spring boot
If you haven’t starting working with spring boot yet, you will quickly find that it pulls out all th ...
- COJN 0584 800603吃糖果
800603吃糖果 难度级别:B: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名( ...