网络流 最大流 Drainage Ditches Dinic
hdu 1532
题目大意:
就是由于下大雨的时候约翰的农场就会被雨水给淹没,无奈下约翰不得不修建水沟,而且是网络水沟,并且聪明的约翰还控制了水的流速,本题就是让你求出最大流速,无疑要运用到求最大流了。题中N为水沟数,M为水沟的顶点,接下来Si,Ei,Ci分别是水沟的起点,终点以及其容量。求源点1到终点M的最大流速。注意重边
Dinic算法的实现有以下几个步骤:
1:初始化容量网络和网络流
2:构造残留网络和层次网络,若汇点不在层次网络中则算法结束 输出最大流
3:在层次网络中用一次DFS进行增广,DFS执行完毕,该阶段的增广也就完毕了。
4:转至步骤2
#include<iostream> using namespace std; #include<cstdio> #include<queue> #define INF 0x7fffffff #define min(a,b) a<b?a:b int N,M; int level[205]; int Si,Ei,Ci; struct Dinic { int c; int f; }edge[205][205]; bool dinic_bfs()//构造层次网络 { queue<int> Q; memset(level,0,sizeof(level));//初始化顶点的层次 为0 Q.push(1); level[1]=1; int u,v; while(!Q.empty()) { u=Q.front(); Q.pop(); for(v=1;v<=M;v++) { if(!level[v]&&edge[u][v].c>edge[u][v].f)//即顶点未被访问过,顶点u,v,存在边 { level[v]=level[u]+1;//给顶点标记层次 Q.push(v); } } } return level[M]!=0;//若返回false表明 汇点不在层次网络中 } int dinic_dfs(int u,int cp)//进行增广 { int tmp=cp; int v,t; if(u==M) return cp; for(v=1;v<=M&&tmp;v++) { if(level[u]+1==level[v]) { if(edge[u][v].c>edge[u][v].f) { t=dinic_dfs(v,min(tmp,edge[u][v].c-edge[u][v].f)); edge[u][v].f+=t; edge[v][u].f-=t; tmp-=t; } } } return cp-tmp; } int dinic()//求出最大流 { int sum,tf; sum=tf=0; while(dinic_bfs()) { while(tf=dinic_dfs(1,INF)) { sum+=tf; } } return sum; } int main() { while(~scanf("%d%d",&N,&M)) { memset(edge,0,sizeof(edge)); while(N--) { scanf("%d%d%d",&Si,&Ei,&Ci); edge[Si][Ei].c+=Ci;//防止重边 } int S=dinic(); printf("%d\n",S); } return 0; } </span>
hdu 3572
题意:
给N个任务,M台机器。每个任务有最早才能开始做的时间S,deadline E,和持续工作的时间P。每个任务可以分段进行,但是在同一时刻,一台机器最多只能执行一个任务. 问存不存在可行的工作时间。
分析:
由于时间<=500且每个任务都能断断续续的执行,那么我们把每一天时间作为一个节点来用网络流解决该题.
建图: 源点s(编号0), 时间1-500天编号为1到500, N个任务编号为500+1 到500+N, 汇点t(编号501+N).
源点s到每个任务i有边(s, i, Pi)
每一天到汇点有边(j, t, M) (其实这里的每一天不一定真要从1到500,只需要取那些被每个任务覆盖的每一天即可)
如果任务i能在第j天进行,那么有边(i, j, 1) 注意由于一个任务在一天最多只有1台机器执行,所以该边容量为1,不能为INF或M哦.
最后看最大流是否等于所有任务所需要的总天数.
#include <bits/stdc++.h> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> #define INF 1e9 using namespace std; const int maxn = 1000 + 10; struct Edge { int from, to, cap, flow; Edge() {} Edge(int f, int t, int c, int fl): from(f), to(t), cap(c), flow(fl) {} }; struct Dinic { int n, m, s, t; vector<Edge> edges; vector<int> G[maxn]; bool vis[maxn]; int cur[maxn]; int d[maxn]; void init(int n, int s, int t) { this->n = n, this->s = s, this->t = t; edges.clear(); for (int i = 0; i < n; ++i) { G[i].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() { queue<int> Q; memset(vis, 0, sizeof(vis)); vis[s] = true; d[s] = 0; Q.push(s); 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] = true; 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[e.to] == d[x] + 1 && (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 max_flow() { int ans = 0; while (BFS()) { memset(cur, 0, sizeof(cur)); ans += DFS(s, INF); } return ans; } } DC; int full_flow; int main() { int T; scanf("%d", &T); for (int kase = 1; kase <= T; ++kase) { int n, m; scanf("%d%d", &n, &m); full_flow = 0; int src = 0, dst = 500 + n + 1; DC.init(500 + 2 + n, src, dst); bool vis[maxn];//表示第i天是否被用到 memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; ++i) { int P, S, E; scanf("%d%d%d", &P, &S, &E); DC.AddEdge(src, 500 + i, P); full_flow += P; for (int j = S; j <= E; ++j) { DC.AddEdge(500 + i, j, 1); vis[j] = true; } } for (int i = 1; i <= 500; ++i)if (vis[i]) //被任务覆盖的日子才添加边 { DC.AddEdge(i, dst, m); } printf("Case %d: %s\n\n", kase, DC.max_flow() == full_flow ? "Yes" : "No"); } return 0; }