这道题目比前面一道求满流的题目多了一点不一样,我理解就是离散化,因为si,ei的范围实在太大,但n的范围却不大,则
把所有si,ei列出来,排序,得到最多2*n-1个区间,则每个区间就是各节点,到汇点的容量限制就是m*区间长度。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=1<<30;
int si[210],ei[210],ni[210],ti[210],head[2100],h[2100],num[4200];
int a[410],n,m,sum;
int cnt,ans,c;
struct edge
{
int x,y,flow,nxt,op;
}em[1000010];
void add(int x,int y,int c)
{
em[++cnt].x=x;
em[cnt].y=y;
em[cnt].flow=c;
em[cnt].nxt=head[x];
head[x]=cnt;
em[cnt].op=cnt+1;
cnt++;
em[cnt].x=y;
em[cnt].y=x;
em[cnt].flow=0;
em[cnt].nxt=head[y];
head[y]=cnt;
em[cnt].op=cnt-1;
}
int dfs(int x,int flow)
{
if(x==n+c)
return flow;
int temp=flow,pos=n+c+1;
for(int j=head[x];j;j=em[j].nxt)
{
int y=em[j].y;
int w=em[j].flow;
if(h[x]==h[y]+1&&w>0)
{
int temp_flow=dfs(y,min(temp,w));
temp-=temp_flow;
em[j].flow-=temp_flow;
em[em[j].op].flow+=temp_flow;
if(!temp||h[0]==n+c+1)
return flow-temp;
}
if(w>0&&h[y]<pos)
pos=h[y];
}
if(temp==flow)
{
num[h[x]]--;
if(num[h[x]]==0)
h[0]=n+c+1;
else
{
h[x]=pos+1;
num[h[x]]++;
}
}
return flow-temp;
}
void isap()
{
memset(h,0,sizeof(h));
memset(num,0,sizeof(num));
while(h[0]<n+c+1)
{
ans+=dfs(0,INF);
}
// printf("%d %d\n",sum,ans);
if(ans==sum)
printf("Yes\n");
else
printf("No\n");
}
int main()
{
while(2==scanf("%d%d",&n,&m))
{
sum=0;
int tot=0;
cnt=0;
memset(head,0,sizeof(head));
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",si+i,ni+i,ei+i,ti+i);
a[++tot]=si[i];
a[++tot]=ei[i];
add(0,i,ni[i]*ti[i]);
sum+=ni[i]*ti[i];
}
sort(a+1,a+tot+1);
c=0;
for(int i=1;i<=tot;i++)
if(a[c]!=a[i])
a[++c]=a[i];
/* for(int i=1;i<=c;i++)
printf("%d\n",a[i]);*/
for(int i=1;i<=c-1;i++)
{
int num=(a[i+1]-a[i])*m;
add(n+i,n+c,num);
}
for(int i=1;i<=c-1;i++)
{
for(int j=1;j<=n;j++)
if(si[j]<=a[i]&a[i+1]<=ei[j])
add(j,i+n,INF);
}
ans=0;
isap();
}
return 0;
}