这题开始用EK敲的,结果TLE到死,然后在网上看到说sap比EK要快,然后就各种搜sap算法,贴个代码在这,但是个模板吧。
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stack>
#include<queue>
#include<math.h>
#include<cstdio>
#define mm(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1111;
const int maxm=505000;
const int inf=0x7fffff;
struct Node
{
int u,v,w;
int next;
}edge[maxm];
int cur[maxn],pre[maxn];
int dis[maxn],gap[maxn];
int minf[maxn],head[maxn];
int idx;
void addEdge(int u, int v, int w)
{
edge[idx].u=u;
edge[idx].v=v;
edge[idx].w=w;
edge[idx].next=head[u];
head[u]=idx++;
edge[idx].u=v;
edge[idx].v=u;
edge[idx].w=0;
edge[idx].next=head[v];
head[v]=idx++;
}
int sap(int s, int t, int n)
{
int max_flow=0,v,u=s;
int id,mindis;
minf[s]=inf;
pre[s]=-1;
mm(dis,0);
mm(gap,0);
gap[0]=n;
for(int i=0;i<=n;++i)
cur[i]=head[i];
while(dis[s]<n)
{
bool flag=false;
if(u==t)
{
max_flow+=minf[t];
for(v=pre[t];v!=-1;v=pre[v])
{
id=cur[v];
edge[id].w-=minf[t];
edge[id^1].w+=minf[t];
minf[v]-=minf[t];
if(edge[id].w==0) u=v;
}
}
for(id=cur[u];id!=-1;id=edge[id].next)
{
v=edge[id].v;
if(edge[id].w>0 && dis[u]==dis[v]+1)
{
flag=true;
pre[v]=u;
cur[u]=id;
minf[v]=min(minf[u],edge[id].w);
u=v;
break;
}
}
if(flag==false)
{
if(--gap[dis[u]]==0) break;
mindis=n;
cur[u]=head[u];
for(id=head[u];id!=-1;id=edge[id].next)
{
v=edge[id].v;
if(edge[id].w>0 && dis[v]<mindis)
{
mindis=dis[v];
cur[u]=id;
}
}
dis[u]=mindis+1;
gap[dis[u]]++;
if(u!=s) u=pre[u];
}
}
return max_flow;
}
int main()
{
int t,n,m,pi,si,ei;
int Max,sum,source,sink,vn;
scanf("%d",&t);
for(int cas=1;cas<=t;++cas)
{
idx=0;
mm(head,-1);
sum=0;
source=0;
Max=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d%d%d",&pi,&si,&ei);
sum+=pi;
Max=max(Max,ei);
addEdge(source,i,pi);
for(int j=n+si;j<=n+ei;++j)
addEdge(i,j,1);
}
sink=n+Max+1;
vn=sink+1;
for(int i=n+1;i<=n+Max;++i)
addEdge(i, sink, m);
printf("Case %d: ",cas);
if(sap(source, sink, vn)==sum)
puts("Yes");
else puts("No");
puts("");
}
return 0;
}