[Luogu] P2859 [USACO06FEB]Stall Reservations S
Description
约翰的\(N(1<N< 50000)\)头奶牛实在是太难伺候了,她们甚至有自己独特的产奶时段。当然对于某一头奶牛,她每天的产奶时段是固定的,为时间段\(A\)到\(B\)(包括时间段\(A\)和时间段\(B\))。显然,约翰必须开发一个调控系统来决定每头奶牛应该被安排到哪个牛棚去挤奶,因为奶牛们显然不希望在挤奶时被其它奶牛看见。
约翰希望你帮他计算一下:如果要满足奶牛们的要求,并且每天每头奶牛都要被挤过奶,至少需要多少牛棚;每头牛应该在哪个牛棚被挤奶。如果有多种答案,你只需任意一种即可。
Solution
这个题的贪心思路是很明显的。就是先把时间段按\(l\)排序,然后不冲突就都安排到一个牛棚,安排完后再开一个新的牛棚。然后找对应牛棚可以建一个有向图,\((x,y)\)表示排完序后\(y\)是\(x\)后第一个不和它冲突的牛棚,能缩小找的范围。建了图就可以跑深搜了。
Code
#include <bits/stdc++.h>
using namespace std;
int n, t, tot, vis[50005], hd[50005], to[50005], nxt[50005], bl[50005];
struct node
{
int l, r, id;
}p[50005];
int read()
{
int x = 0, fl = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
return x * fl;
}
void add(int x, int y)
{
tot ++ ;
to[tot] = y;
nxt[tot] = hd[x];
hd[x] = tot;
return;
}
bool operator < (const node &x, const node &y)
{
return x.l < y.l || x.l == y.l && x.r < y.r;
}
void dfs(int x)
{
vis[p[x].id] = t;
for (int i = hd[x]; i; i = nxt[i])
{
int y = to[i];
if (!vis[p[y].id])
{
dfs(y);
return;
}
else
{
for (int q = y + 1; q <= n; q ++ )
{
if (!vis[p[q].id] && p[q].l >= p[x].r + 1)
{
dfs(q);
return;
}
}
}
}
return;
}
int main()
{
n = read();
for (int i = 1; i <= n; i ++ )
p[i].l = read(), p[i].r = read(), p[i].id = i;
sort(p + 1, p + n + 1);
for (int i = 1; i <= n; i ++ )
{
int pos = lower_bound(p + 1, p + n + 1, (node){p[i].r + 1, 0}) - p;
if (pos != n + 1) add(i, pos);
}
for (int x = 1; x <= n; x ++ )
if (!vis[p[x].id])
t ++ , dfs(x);
printf("%d\n", t);
for (int i = 1; i <= n; i ++ )
printf("%d\n", vis[i]);
return 0;
}