HDU 3572 最大流

最近在刷題和各種事情,忘記更新了,最近會把做的題目都更新出來


Task Schedule

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6018    Accepted Submission(s): 1927


Problem Description
Our geometry princess XMM has stoped her study in computational geometry to concentrate on her newly opened factory. Her factory has introduced M new machines in order to process the coming N tasks. For the i-th task, the factory has to start processing it at or after day Si, process it for Pi days, and finish the task before or at day Ei. A machine can only work on one task at a time, and each task can be processed by at most one machine at a time. However, a task can be interrupted and processed on different machines on different days. 
Now she wonders whether he has a feasible schedule to finish all the tasks in time. She turns to you for help.
 

Input
On the first line comes an integer T(T<=20), indicating the number of test cases.

You are given two integer N(N<=500) and M(M<=200) on the first line of each test case. Then on each of next N lines are three integers Pi, Si and Ei (1<=Pi, Si, Ei<=500), which have the meaning described in the description. It is guaranteed that in a feasible schedule every task that can be finished will be done before or at its end day.
 

Output
For each test case, print “Case x: ” first, where x is the case number. If there exists a feasible schedule to finish all the tasks, print “Yes”, otherwise print “No”.

Print a blank line after each test case.
 

Sample Input
2 4 3 1 3 5 1 1 4 2 3 7 3 5 9 2 2 2 1 3 1 2 2
 

Sample Output
Case 1: Yes Case 2: Yes
 

Author
allenlowesy
 

Source
 

Recommend
zhouzeyong
 


/************************************************

Desiner:hl
time:2015/11/01
Exe.Time:187MS
Exe.Memory:5776K

題意:有M個機器,有N個任務。每個任務必須在Si 或者以後開始做,在Ei 或者之前完成,
完成任務必須處理Pi 個時間單位。其中,每個任務可以在任意(空閒)機器上工作,每個
機器的同一時刻只能工作一個任務,每個任務在同一時刻只能被一個機器工作,而且任務做
到一半可以打斷,拿去其他機器做。問:能否在規定時間內把任務做完。 

題解:源點到每個任務建立一條值爲完成該任務需要的天數的邊
任務到該任務開始到該任務結束的所有天數分別建立一條爲1的邊
天數到匯點建立一條爲題目中機械數量的邊
如果sap算出來的結果是等於他所需要的天數的。說明他們能完成 

************************************************/

#include <iostream>    
#include <algorithm>    
#include <cstring>    
#include <string>    
#include <cstdio>    
#include <cmath>      
    
using namespace std;    
const int MAXN = 100010 ; //點數最大值      
const int MAXM = 400010 ; //邊數最大值      
const int INF = 0x3f3f3f3f;      
  
int S,V,N,M;  


int maxday;
 
struct Edge{      
    int to,next,cap,flow;      
}edge[MAXM];//注意是MAXM      
int tol;      
int head[MAXN];      
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];       
int aa[555],bb[555],cc[555];   

    
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].next = head[u];      
    edge[tol].flow = 0;      
    head[u] = tol++;      
    edge[tol].to = u;      
    edge[tol].cap = rw;      
    edge[tol].next = head[v];      
    edge[tol].flow = 0;      
    head[v] = tol++;      
}      
  //最大流開始     
int sap(int start,int end,int N){      
    memset(gap,0,sizeof(gap));      
    memset(dep,0,sizeof(dep));      
    memcpy(cur,head,sizeof(head));      
    int u = start;      
    pre[u] = -1;      
    gap[0] = N;      
    int ans = 0;      
    while(dep[start] < N){      
        if(u==end){      
            int Min = INF;      
            for(int i=pre[u];i!= -1; i=pre[edge[i^1].to])      
                if(Min > edge[i].cap - edge[i].flow)      
                    Min = edge[i].cap - edge[i].flow;      
                          
            for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]){      
                edge[i].flow += Min;      
                edge[i^1].flow -=Min;      
            }      
            u=start;      
            ans +=Min;      
            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]=pre[v]=i;      
                break;      
            }      
        }      
        if(flag){      
            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[pre[u]^1].to;      
    }      
    return ans;      
}      
//最大流結束     
  
int build(){  
    int i,j,k,l,m,n;  
    init();  
    for(i=1;i<=N;i++){  
       addedge(S,i,aa[i]);//源點到每個任務的連線爲PI 
       for(j=bb[i];j<=cc[i];j++){
       		addedge(i,N+j,1); //從這個任務到這個任務開始的時間到結束的時間連一條爲1的邊 
       }
    } 
	for(j=1;j<=maxday;j++){
		addedge(j+N,V,M); 
	}
    int orz=sap(S,V,V+1);  
    return orz;  
      
}  
  
  
  
bool solve(int su){    
    int i,j,k;  
    
	int ans; 
    ans = build();
    if(ans==su){
    	printf("Yes\n");
    } 
    else{
    	printf("No\n");
    }
      
}    
    
int main(){     

	int T;
    int m,n,q,p;      
    int i,j,k,a,b,c; 
	int pisum;  
	scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
    	scanf("%d%d",&N,&M);  
 		pisum=maxday=0;
	    for(i=1;i<=N;i++){  
	        scanf("%d%d%d",&aa[i],&bb[i],&cc[i]);  
			pisum+=aa[i];
			maxday=max(maxday,cc[i]);
	    } 
	    S=0;
	    V=N+maxday+1;

    	printf("Case %d: ",cas);
     	solve(pisum);
		puts("");
    }
    
	
	 
    return 0;  
}      


發佈了80 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章