P2887 [USACO07NOV]防晒霜Sunscreen

题目描述

To avoid unsightly burns while tanning, each of the C (1 ≤ C ≤ 2500) cows must cover her hide with sunscreen when they're at the beach. Cow i has a minimum and maximum SPF rating (1 ≤ minSPFi ≤ 1,000; minSPFi ≤ maxSPFi ≤ 1,000) that will work. If the SPF rating is too low, the cow suffers sunburn; if the SPF rating is too high, the cow doesn't tan at all........

The cows have a picnic basket with L (1 ≤ L ≤ 2500) bottles of sunscreen lotion, each bottle i with an SPF rating SPFi (1 ≤ SPFi ≤ 1,000). Lotion bottle i can cover coveri cows with lotion. A cow may lotion from only one bottle.

What is the maximum number of cows that can protect themselves while tanning given the available lotions?

有\(C\)个奶牛去晒太阳 (1 <=\(C\) <= 2500),每个奶牛各自能够忍受的阳光强度有一个最小值和一个最大值,太大就晒伤了,太小奶牛没感觉。

而刚开始的阳光的强度非常大,奶牛都承受不住,然后奶牛就得涂抹防晒霜,防晒霜的作用是让阳光照在身上的阳光强度固定为某个值。

那么为了不让奶牛烫伤,又不会没有效果。

给出了\(L\)种防晒霜。每种的数量和固定的阳光强度也给出来了

每个奶牛只能抹一瓶防晒霜,最后问能够享受晒太阳的奶牛有几个。

输入输出格式

输入格式:

  • Line 1: Two space-separated integers: \(C\) and \(L\)

  • Lines 2..\(C+1\): Line i describes cow i's lotion requires with two integers: \(minSPFi\) and \(maxSPFi\)

  • Lines \(C+2\)..\(C+L+1\): Line \(i+C+1\) describes a sunscreen lotion bottle \(i\) with space-separated integers: \(SPFi\) and \(coveri\)

输出格式:

A single line with an integer that is the maximum number of cows that can be protected while tanning


\(DINIC\)周常写爆:(1/1)

思路:s连每头牛边1,每头牛连合法的防晒霜边1,防晒霜连t使用次数,跑最大流即可。(此题也有别的解法)

前后代码对比:

54分:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int min(int x,int y){return x<y?x:y;}
const int N=2508;
const int inf=0x3f3f3f3f;
int C,L,l[N],r[N],T;
struct Edge
{
int next,to,w;
}edge[N*N];
int head[N<<2],cnt=-1;
void add(int u,int v,int w)
{
edge[++cnt].next=head[u];edge[cnt].to=v;edge[cnt].w=w;head[u]=cnt;
}
int dep[N<<2],s[N<<2],pre[N<<2],used[N<<2],tot=0,ans=0;
queue <int > q;
void push(int x){s[++tot]=x;}
void pop(){tot--;}
bool bfs()
{
memset(dep,0,sizeof(dep));
while(!q.empty()) q.pop();
q.push(0);
dep[0]=1;
while(!q.empty()&&q.front()!=T)
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to,w=edge[i].w;
if(!dep[v]&&w)
{
dep[v]=dep[u]+1;
q.push(v);
}
}
}
return !q.empty();
}
int main()
{
scanf("%d%d",&C,&L);
memset(head,-1,sizeof(head));
T=C+L+1;
for(int i=1;i<=C;i++)
{
scanf("%d%d",l+i,r+i);
add(0,i,1),add(i,0,0);
}
int num,d;
for(int i=1;i<=L;i++)
{
scanf("%d%d",&d,&num);
for(int j=1;j<=C;j++)
if(l[j]<=d&&d<=r[j])
add(j,i+C,1),add(i+C,j,0);
add(i+C,T,num),add(T,i+C,0);
}
while(bfs())
{
push(0);
memset(used,0,sizeof(used));
memset(pre,0,sizeof(pre));
while(tot)
{
if(s[tot]==T)
{
int now=tot,id,m_min=inf;
while(pre[s[now]])
{
if(m_min>=edge[pre[s[now]]].w)
{
m_min=edge[pre[s[now]]].w;
id=now-1;
}
now--;
}
ans+=m_min;now=tot;
while(pre[s[now]])
{
edge[pre[s[now]]].w-=m_min;
edge[pre[s[now]]^1].w+=m_min;
now--;
}
tot=id;
used[T]=0;
}
else
{
int u=s[tot];
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to,w=edge[i].w;
if(!used[v]&&dep[v]==dep[u]+1&&w)
{
push(v);
pre[v]=i;
used[v]=1;
break;
}
}
if(s[tot]==u) pop();
}
}
}
printf("%d\n",ans);
return 0;
}

100分:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int min(int x,int y){return x<y?x:y;}
const int N=2508;
const int inf=0x3f3f3f3f;
int C,L,l[N],r[N],T;
struct Edge
{
int next,to,w;
}edge[N*N];
int head[N<<2],cnt=-1;
void add(int u,int v,int w)
{
edge[++cnt].next=head[u];edge[cnt].to=v;edge[cnt].w=w;head[u]=cnt;
}
int dep[N<<2],s[N<<2],pre[N<<2],used[N<<2],tot=0,ans=0;
queue <int > q;
void push(int x){s[++tot]=x;}
void pop(){tot--;}
bool bfs()
{
memset(dep,0,sizeof(dep));
while(!q.empty()) q.pop();
q.push(0);
dep[0]=1;
while(!q.empty()&&q.front()!=T)
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to,w=edge[i].w;
if(!dep[v]&&w)
{
dep[v]=dep[u]+1;
q.push(v);
}
}
}
return !q.empty();
}
int main()
{
scanf("%d%d",&C,&L);
memset(head,-1,sizeof(head));
T=C+L+1;
for(int i=1;i<=C;i++)
{
scanf("%d%d",l+i,r+i);
add(0,i,1),add(i,0,0);
}
int num,d;
for(int i=1;i<=L;i++)
{
scanf("%d%d",&d,&num);
for(int j=1;j<=C;j++)
if(l[j]<=d&&d<=r[j])
add(j,i+C,1),add(i+C,j,0);
add(i+C,T,num),add(T,i+C,0);
}
while(bfs())
{
push(0);
memset(used,0,sizeof(used));
memset(pre,-1,sizeof(pre));
while(tot)
{
if(s[tot]==T)
{
int now=tot,id,m_min=inf;
while(pre[s[now]]!=-1)
{
if(m_min>=edge[pre[s[now]]].w)
{
m_min=edge[pre[s[now]]].w;
id=now-1;
}
now--;
}
ans+=m_min;now=tot;
while(pre[s[now]]!=-1)
{
edge[pre[s[now]]].w-=m_min;
edge[pre[s[now]]^1].w+=m_min;
now--;
}
tot=id;
used[T]=0;
}
else
{
int u=s[tot];
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to,w=edge[i].w;
if(!used[v]&&dep[v]==dep[u]+1&&w)
{
push(v);
pre[v]=i;
used[v]=1;
break;
}
}
if(s[tot]==u) pop();
}
}
}
printf("%d\n",ans);
return 0;
}

0和-1的锅。。。


2018.6.8

04-21 12:19