标签:最大流
题意:某个工厂有M台机器,需要完成N项任务。给出每项任务的完成时间PI,开始时间SI,结束时间EI;现在问你能否在刚好完成(一次);
解析:以时间为单元构图,即将完成某一任务 I ,所需要时间PI,拆分成PI个单元1.然后设置源点s( 0 )和终点t( n + maxday + 1 ).那么从源点到完成第i个任务则其权值为完成当前任务所需要的时间PI。然后从当前任务 i 与其完成的时段SI ~ EI 赋值为1( 每天一台机器,所以完成的是1个单元,从而进行连通)。同理,有M台机器,因此,到达终点的权值为M,即1 * M;
然后使用最大流即可。
#include <fstream> #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN = 100010;//点数最大值 const int MAXM = 400010;//边数最大值 const int INF = 0x3f3f3f3f; struct Edge { int to,next,cap,flow; }edge[MAXM];//注意是MAXN int tol; int head[MAXN]; int gap[MAXN],dep[MAXN],cur[MAXN]; void init() { tol = 0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w,int rw = 0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[MAXN]; void BFS(int start,int end) { memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while(front != rear) { int u = Q[front++]; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[MAXN]; int sap(int start,int end,int N) { BFS(start,end); memcpy(cur,head,sizeof(head)); int top = 0; int u = start; int ans = 0; while(dep[start] < N) { if(u == end) { int Min = INF; int inser; for(int i = 0;i < top;i++) if(Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for(int i = 0;i < top;i++) { edge[S[i]].flow += Min; edge[S[i]^1].flow -= Min; } ans += Min; top = inser; u = edge[S[top]^1].to; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = i; break; } } if(flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for(int i = head[u]; i != -1; i = edge[i].next) if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u] = Min + 1; gap[dep[u]]++; if(u != start) u = edge[S[--top]^1].to; } return ans; } /*最大流模板*/ int main(){ int Case; int n, m; scanf( "%d", &Case ); for( int k = 1; k <= Case; ++k ){ scanf( "%d%d", &n, &m ); init(); int value, start, end, s = 0, e = 0,sum = 0, Max = 0; for( int i = 1; i <= n; ++i ){ scanf( "%d%d%d", &value, &start, &end ); Max = max( Max, end ); sum += value; addedge( s, i, value ); for( int j = start; j <= end; ++j ){ addedge( i, n + j, 1 ); } } int N = n + 1 + Max; for( int i = 1; i <= Max; ++i ){ addedge( i + n, N, m ); } int ans = sap( s, N, N); if( ans == sum ){ printf( "Case %d: Yes\n\n", k ); } else{ printf( "Case %d: No\n\n", k ); } } return 0; }
标签:最大流
原文地址:http://blog.csdn.net/bo_jwolf/article/details/37909747