HDU ACM 3572 Task Schedule 网络最大流

分析:

建图:每个任务和每一天分别看做一个点,添加源和汇点。源点和每个任务连一条边,每天边的容量为完成对应任务所需处理次数。若第i个任务能够在Si至Ei天处理,则由该任务向这些天分别连一条边,容量为1,表示此任务每天只能被处理一次。最后,每一天分别连一条边到汇点,容量为机器数M,即每天可以处理M个任务。若求出的最大流等于所有任务需要处理的次数之和,说明能完成任务;否则,不能。

#include<iostream>#include<vector>#include<queue>using namespace std;#define N 1111#define INF 0x7fffffff#define min(a,b) ((a)<(b)?(a):(b))class Max_Flow//DINIC算法{private:struct EDGE{EDGE(int _from,int _to,int _cap,int _flow){from=_from;to=_to;cap=_cap;flow=_flow;}int from,to,cap,flow;};public:Max_Flow(){ m_iM=0;}~Max_Flow(){}void AddEdge(int _from,int _to,int _cap); //_cap表示容量int MaxFlow(int s,int t);private:bool BFS();//BFS建立分层图int DFS(int x,int a); //DFS进行多路增广int m_iM,m_iS,m_iT; //边数(包括反向边),源点,汇点vector<EDGE> m_vEdges;//边表m_edges[e]和m_edges[e^1]互为反向弧vector<int> m_vG[N];//领接表bool m_bVis[N];//BFS使用的访问数组int m_iD[N];//从源点到点i的距离int m_iCur[N];//表示当前弧的下标};int Max_Flow::MaxFlow(int s,int t){int flow=0;this->m_iS=s;this->m_iT=t;while(BFS()){memset(m_iCur,0,sizeof(m_iCur));flow+=DFS(s,INF);}return flow;}int Max_Flow::DFS(int x,int a){int _flow,f;if(x==m_iT || a==0) return a;_flow=0;int& i=m_iCur[x];//从上次弧考虑,避免不必要的重复搜索for(;i<m_vG[x].size();i++){EDGE& e=m_vEdges[m_vG[x][i]];if(m_iD[x]+1==m_iD[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0){e.flow+=f;m_vEdges[m_vG[x][i]^1].flow-=f;//反向边_flow+=f;a-=f;if(a==0) break;}}return _flow;}bool Max_Flow::BFS(){memset(m_bVis,0,sizeof(m_bVis));queue<int> q;int x,i;q.push(m_iS);m_iD[m_iS]=0;m_bVis[m_iS]=1;while(!q.empty()){x=q.front();q.pop();for(i=0;i<m_vG[x].size();i++){EDGE& e=m_vEdges[m_vG[x][i]];if(!m_bVis[e.to] && e.cap>e.flow)//只需要考虑残量网络中的弧{m_bVis[e.to]=1;m_iD[e.to]=m_iD[x]+1;q.push(e.to);}}}return m_bVis[m_iT];}void Max_Flow::AddEdge(int _from,int _to,int _cap){m_vEdges.push_back(EDGE(_from,_to,_cap,0));m_vEdges.push_back(EDGE(_to,_from,0,0));m_iM+=2;m_vG[_from].push_back(m_iM-2);m_vG[_to].push_back(m_iM-1);}int main(){int T,n,M,Pi,Si,Ei,c,i,j,sum,maxday;int s,t;ios::sync_with_stdio(false);cin>>T;c=0;while(T–){cin>>n>>M;Max_Flow max_flow;sum=0;maxday=-1;s=0;for(i=1;i<=n;i++){cin>>Pi>>Si>>Ei;sum+=Pi;maxday=maxday>Ei?maxday:Ei;max_flow.AddEdge(s,i,Pi); //源点和第i个任务建边,容量为完成任务天数for(j=Si;j<=Ei;++j)max_flow.AddEdge(i,n+j,1);//任务和第j天建边,容量为1}t=n+maxday+1;for(i=1;i<=maxday;i++)max_flow.AddEdge(n+i,t,M); //天数和汇点建边,,表示每天有m台机器if(sum==max_flow.MaxFlow(s,t))//若最大流等于需要天数之和则可以完成cout<<"Case "<<++c<<": Yes"<<endl;elsecout<<"Case "<<++c<<": No"<<endl;cout<<endl;}return 0;}

勤奋,它是一块可以吸引到一切美好事物的天然磁石,它比黄金珍贵,

HDU ACM 3572 Task Schedule 网络最大流

相关文章:

你感兴趣的文章:

标签云: