Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 489 Accepted Submission(s): 211
最大流的题目。
题意比较难懂的。
出题人解题报告:
将所有的到达时间和结束时间按升序排序,得到 x <= 2n-1 个时间区间。建立网络流模型:s为源,t为汇,每个顾客i作为一个结点并连边(s, i, ni*ti),每个区间j作为一个结点并连边(j, t, (ej-sj)*M),其中sj, ej分别表示区间j的起始时间和终止时间。对任意顾客i和区间j,若 [sj, ej] 完全包含在 [si, ei] 之中,则连边(i, j, INF)。若最大流等于 ∑ni*ti 则是 Yes,否则是 No。
注意,这个题目的e[i]是不能算上去的
//============================================================================ // Name : HDU.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> using namespace std; const int MAXN=1010; const int MAXM=200010; const int INF=0x3f3f3f3f; struct Node { int to,next,cap; }edge[MAXM]; int tol; int head[MAXN]; int gap[MAXN],dis[MAXN],pre[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].next=head[u];head[u]=tol++; edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];head[v]=tol++; } int sap(int start,int end,int nodenum) { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); memcpy(cur,head,sizeof(head)); int u=pre[start]=start,maxflow=0,aug=-1; gap[0]=nodenum; while(dis[start]<nodenum) { loop: for(int &i=cur[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap&&dis[u]==dis[v]+1) { if(aug==-1||aug>edge[i].cap) aug=edge[i].cap; pre[v]=u; u=v; if(v==end) { maxflow+=aug; for(u=pre[u];v!=start;v=u,u=pre[u]) { edge[cur[u]].cap-=aug; edge[cur[u]^1].cap+=aug; } aug=-1; } goto loop; } } int mindis=nodenum; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap&&mindis>dis[v]) { cur[u]=i; mindis=dis[v]; } } if((--gap[dis[u]])==0)break; gap[dis[u]=mindis+1]++; u=pre[u]; } return maxflow; } int n[210],s[210],e[210],t[210]; int a[1000]; int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int N,M; while(scanf("%d%d",&N,&M)==2) { init(); int sum=0; int num=0; for(int i=1;i<=N;i++) { scanf("%d%d%d%d",&s[i],&n[i],&e[i],&t[i]); sum+=n[i]*t[i]; addedge(0,i,n[i]*t[i]); a[num++]=s[i]; a[num++]=e[i]; } sort(a,a+num); num=unique(a,a+num)-a; int start=0,end=N+num,nodenum=end+1; for(int i=0;i<num-1;i++) { addedge(N+1+i,end,(a[i+1]-a[i])*M); for(int j=1;j<=N;j++) if(s[j]<=a[i]&&e[j]>=a[i+1]) addedge(j,N+1+i,INF); } if(sap(start,end,nodenum)==sum)printf("Yes\n"); else printf("No\n"); } return 0; }