该题非常经典,建图的方法非常巧妙,因为每个任务的完成不一定要连续,而且可以换机器完成,而且我们注意到时间点最多500,很小,所以我们将时间点抽出来建图。
对于每个任务,将其时间范围内的点与之连起来,容量显然为1 ,并与汇点相连,容量为p[i] 。 对于每个时间点,因为最多可以有m台机器同时工作,所以容量为m 。
一开始老想着任务和机器之间怎么建立联系了。
推荐题目: 点击打开链接
细节参见代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 100000000; const int maxn = 2000 ; int T,cnt,a,b,m,p[maxn],s[maxn],e[maxn],d,kase = 0,v,c,n; struct Edge { int from, to, cap, flow; }; bool operator < (const Edge& a, const Edge& b) { return a.from < b.from || (a.from == b.from && a.to < b.to); } struct Dinic { int n, m, s, t; vector<Edge> edges; // 边数的两倍 vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号 bool vis[maxn]; // BFS使用 int d[maxn]; // 从起点到i的距离 int cur[maxn]; // 当前弧指针 void init(int n) { for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from, int to, int cap) { edges.push_back((Edge){from, to, cap, 0}); edges.push_back((Edge){to, from, 0, 0}); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); vis[s] = 1; d[s] = 0; while(!Q.empty()) { int x = Q.front(); Q.pop(); for(int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(!vis[e.to] && e.cap > e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int& i = cur[x]; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) { e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while(BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; } }g; int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); int max_t = 0, flow = 0; for(int i=1;i<=n;i++) { scanf("%d%d%d",&p[i],&s[i],&e[i]); flow += p[i]; max_t = max(max_t,e[i]); } g.init(max_t+n+5); for(int i=1;i<=max_t;i++) { g.AddEdge(0,i,m); } for(int i=1;i<=n;i++) { for(int j=s[i];j<=e[i];j++) g.AddEdge(j,max_t+i,1); g.AddEdge(max_t+i,max_t+n+1,p[i]); } if(flow == g.Maxflow(0,max_t+n+1)) printf("Case %d: Yes\n\n",++kase); else printf("Case %d: No\n\n",++kase); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 3572 Task Schedule(最大流Dinic算法)
原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/48109023