NOIP模拟 正直糖豆(最大流)
【描述】
L为了准备他的正直模拟赛又发明了了一种“教授糖豆”,该糖豆会给服用的人增加一定的正直值。由于机房中N个人的接受能力是有现的,正直值过大会影响和谐,正直值过小又影响团结,所以学员I分到的糖豆的正直值P必须在范围MAXi,MINi之间,既MINi<=P<=MAXi。给出M种糖豆及每种的个数,以及机房中每个人可接受的的正直范围,求最多能有几个人同时得到合适的糖豆。每个人最多得到一个糖豆。
【输入】
第一行:两个整数N和M
第二到N+1行:每行两个整数MINi,MAXi。第i行表示第i-1个人可接受的正直范围。
第N+2行到第N+M+1行:每行两个整数,分别表示糖豆的正直值和数量。
输出
一行一个整数表示最多有多少个人能同时得到合适的糖豆。
【样例输入】
3 2
3 10
2 5
1 5
6 2
4 1
【样例输出 】
2
【提示】
100%:1<=n<=2500,1<=m<=2500,1<=MINi,MAXi<=1000,1<=Pi<=1000
这个题的规模非常的迷啊,开了2e6的数组才过。。。总体来说还是很简单的,网络流(或二分图匹配,这里写网络流版本)模板
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=2e6+10;
const ll INF=0x3f3f3f3f;
ll n,m,cnt,stul[MAXN],stur[MAXN],sug[MAXN];
ll head[MAXN],to[MAXN],w[MAXN],nxt[MAXN];
ll cur[MAXN];
ll depth[MAXN],s,t;
ll Read()
{
ll i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
void add(ll x,ll y,ll z)
{
nxt[cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
w[cnt]=z;
cnt++;
}
bool bfs()
{
queue<ll> q;
while(!q.empty())
{
q.pop();
}
for(ll i=0;i<=n+m+1;++i)
depth[i]=0;
depth[s]=1;
q.push(s);
do
{
ll u=q.front();
q.pop();
for(ll i=head[u];i!=-1;i=nxt[i])
{
ll v=to[i];
if(w[i]>0&&depth[v]==0)
{
depth[v]=depth[u]+1;
q.push(v);
}
}
}while(!q.empty());
if(depth[t]==0)
return 0;
return 1;
}
ll dfs(ll u,ll dis)
{
if(u==t)
return dis;
for(ll &i=cur[u];i!=-1;i=nxt[i])
{
ll v=to[i];
if(depth[v]==depth[u]+1&&w[i]!=0)
{
ll di=dfs(v,min(w[i],dis));
if(di>0)
{
w[i]-=di;
w[i^1]+=di;
return di;
}
}
}
return 0;
}
ll dinic()
{
ll ans=0;
while(bfs())
{
for(ll i=0;i<=n+m+1;++i)
cur[i]=head[i];
while(ll d=dfs(s,INF))
ans+=d;
}
return ans;
}
int main()
{
for(ll i=0;i<=n+m+1;++i)
head[i]=nxt[i]=-1;
n=Read(),m=Read();
t=n+m+1;
for(ll i=1;i<=n;++i)
stul[i]=Read(),stur[i]=Read(),add(0,i,1),add(i,0,0);
for(ll i=1;i<=m;++i)
{
ll num;
sug[i]=Read(),num=Read();
add(i+n,t,num),add(t,i+n,0);
for(ll j=1;j<=n;++j)
if(sug[i]>=stul[j]&&sug[i]<=stur[j])
add(j,i+n,1),add(i+n,j,0);
}
printf("%lld",dinic());
return 0;
}