https://vjudge.net/problem/HDU-3572
题意:
有N个作业和M台机器,每个作业都有一个持续时间P,工作的日期为S~E。作业可以断断续续的在不同机器上做,每台机器每次只可以处理一个作业。判断是否可以在作业的工作日期内完成所有作业。
思路:
建立源点0和汇点t,因为天数最多为500,所有我们将日期的编号定为1~500,作业的编号为500+i。
对于每个作业,与源点0相连,容量为P,意味着它必须走完这P容量才能完成这作业。与S~E相连,容量为1。日期与汇点相连,容量为m,说明每天能处理m个作业。
最后计算出最大流,如果等于所有作业的P之和,说明是可以完成的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 8 const int maxn=1000+5; 9 const int INF=0x3f3f3f3f; 10 11 int n,m; 12 int ans; 13 14 struct Edge 15 { 16 int from,to,cap,flow; 17 Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){} 18 }; 19 20 struct Dinic 21 { 22 int n,m,s,t; 23 vector<Edge> edges; 24 vector<int> G[maxn]; 25 bool vis[maxn]; 26 int cur[maxn]; 27 int d[maxn]; 28 29 void init(int n) 30 { 31 this->n=n; 32 for(int i=0;i<n;++i) G[i].clear(); 33 edges.clear(); 34 } 35 36 void AddEdge(int from,int to,int cap) 37 { 38 edges.push_back( Edge(from,to,cap,0) ); 39 edges.push_back( Edge(to,from,0,0) ); 40 m=edges.size(); 41 G[from].push_back(m-2); 42 G[to].push_back(m-1); 43 } 44 45 bool BFS() 46 { 47 queue<int> Q; 48 memset(vis,0,sizeof(vis)); 49 vis[s]=true; 50 d[s]=0; 51 Q.push(s); 52 while(!Q.empty()) 53 { 54 int x=Q.front(); Q.pop(); 55 for(int i=0;i<G[x].size();++i) 56 { 57 Edge& e=edges[G[x][i]]; 58 if(!vis[e.to] && e.cap>e.flow) 59 { 60 vis[e.to]=true; 61 d[e.to]=d[x]+1; 62 Q.push(e.to); 63 } 64 } 65 } 66 return vis[t]; 67 } 68 69 int DFS(int x,int a) 70 { 71 if(x==t || a==0) return a; 72 int flow=0, f; 73 for(int &i=cur[x];i<G[x].size();++i) 74 { 75 Edge &e=edges[G[x][i]]; 76 if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) 77 { 78 e.flow +=f; 79 edges[G[x][i]^1].flow -=f; 80 flow +=f; 81 a -=f; 82 if(a==0) break; 83 } 84 } 85 return flow; 86 } 87 88 int Maxflow(int s,int t) 89 { 90 this->s=s; 91 this->t=t; 92 int flow=0; 93 while(BFS()) 94 { 95 memset(cur,0,sizeof(cur)); 96 flow +=DFS(s,INF); 97 } 98 return flow; 99 } 100 }DC; 101 102 int main() 103 { 104 //freopen("D:\\input.txt","r",stdin); 105 int T; 106 int kase=0; 107 scanf("%d",&T); 108 while(T--) 109 { 110 scanf("%d%d",&n,&m); 111 ans=0; 112 DC.init(500+2+n); 113 114 bool vis[maxn];//表示第i天是否被用到 115 memset(vis,0,sizeof(vis)); 116 117 for(int i=1;i<=n;++i) 118 { 119 int P,S,E; 120 scanf("%d%d%d",&P,&S,&E); 121 DC.AddEdge(0,500+i,P); 122 ans += P; 123 for(int j=S;j<=E;++j) 124 { 125 DC.AddEdge(500+i,j,1); 126 vis[j]=true; 127 } 128 } 129 130 for(int i=1;i<=500;++i)if(vis[i])//被任务覆盖的日子才添加 131 DC.AddEdge(i,500+n+1,m); 132 printf("Case %d: %s\n\n",++kase,DC.Maxflow(0,500+n+1)==ans?"Yes":"No"); 133 } 134 return 0; 135 }
时间: 2024-10-06 16:26:07