[P8095 USACO22JAN] Cereal 2 S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
Farmer John 的奶牛们的早餐最爱当然是麦片了!事实上,奶牛们的胃口是如此之大,每头奶牛一顿饭可以吃掉整整一箱麦片。
最近农场收到了一份快递,内有 M M M 种不同种类的麦片( 2 ≤ M ≤ 1 0 5 2\le M\le 10^5 2≤M≤105)。不幸的是,每种麦片只有一箱! N N N 头奶牛( 1 ≤ N ≤ 1 0 5 1\le N\le 10^5 1≤N≤105)中的每头都有她最爱的麦片和第二喜爱的麦片。给定一些可选的麦片,奶牛会执行如下的过程:
如果她最爱的麦片还在,取走并离开。
否则,如果她第二喜爱的麦片还在,取走并离开。
否则,她会失望地哞叫一声然后不带走一片麦片地离开。
当你最优地排列这些奶牛时,求饥饿的奶牛的最小数量。同时,求出任意一个可以达到此最小值的 N N N 头奶牛的排列。
输入的第一行包含两个空格分隔的整数 N N N 和 M M M。
对于每一个 1 ≤ i ≤ N 1\le i\le N 1≤i≤N,第 i i i 行包含两个空格分隔的整数 f i f_i fi 和 s i s_i si( 1 ≤ f i , s i ≤ M 1\le f_i,s_i\le M 1≤fi,si≤M,且 f i ≠ s i f_i\neq s_i fi=si),为第 i i i 头奶牛最喜爱和第二喜爱的麦片。
输出饥饿的奶牛的最小数量,并输出任意一个可以达到此最小值的 1 … N 1\ldots N 1…N 的排列。如果有多个符合要求的排列,输出任意一个。
8 10
2 1
3 4
2 3
6 5
7 8
6 7
7 5
5 8
1
1
3
2
8
4
6
5
7
【样例解释】
在这个例子中,有 8 8 8 头奶牛和 10 10 10 种麦片。
注意我们对前三头奶牛独立于后五头奶牛求解,因为她们没有共同喜欢的麦片。
如果前三头奶牛按顺序 [ 1 , 2 , 3 ] [1,2,3] [1,2,3] 进行选择,则奶牛 1 1 1 会选择麦片 2 2 2,奶牛 2 2 2 会选择麦片 3 3 3,奶牛 3 3 3 会饥饿。
如果前三头奶牛按顺序 [ 1 , 3 , 2 ] [1,3,2] [1,3,2] 进行选择,则奶牛 1 1 1 会选择麦片 2 2 2,奶牛 3 3 3 会选择麦片 3 3 3,奶牛 2 2 2 会选择麦片 4 4 4;没有奶牛会饥饿。
当然,还存在其他排列使得前三头奶牛均不饥饿。例如,如果前三头奶牛按顺序 [ 3 , 1 , 2 ] [3,1,2] [3,1,2] 选择,则奶牛 3 3 3 会选择麦片 2 2 2,奶牛 1 1 1 会选择麦片 1 1 1,奶牛 2 2 2 会选择麦片 3 3 3;同样,奶牛 [ 1 , 2 , 3 ] [1,2,3] [1,2,3] 均不会饥饿。
可以证明在后五头奶牛中,至少一头会饥饿。
【数据范围】
14 14 14 个测试点中的 4 4 4 个测试点满足 N , M ≤ 100 N,M\le 100 N,M≤100。
14 14 14 个测试点中的 10 10 10 个测试点没有额外限制。
【说明】
本题采用自行编写的 Special Judge。如果对此有疑问或想要 hack,请私信编写者或发帖。
二分图匹配 + 拓扑排序求答案
#include
#define fu(x, y, z) for (int x = y; x <= z; x++)
using namespace std;
const int N = 1e6 + 5;
int n, m, cnt, hd[N], a[N], b[N], vis[N], flg[N], len , ct[N] , ru[N];
struct RE {
int f, s;
} t[N];
struct node {
int to, nt;
} e[N << 2];
void add(int x, int y) { e[++cnt].to = y, e[cnt].nt = hd[x], hd[x] = cnt , ru[y] ++; }
int dfs(int x) {
if (!vis[t[x].f]) {
vis[t[x].f] = 1;
if (!b[t[x].f] || dfs (b[t[x].f])) {
a[x] = t[x].f , b[t[x].f] = x;
vis[t[x].f] = 0;
return 1;
}
}
if (!vis[t[x].s]) {
vis[t[x].s] = 1;
if (!b[t[x].s] || dfs (b[t[x].s])) {
a[x] = t[x].s , b[t[x].s] = x;
vis[t[x].s] = 0;
return 1;
}
}
return 0;
}
void fans(int x) {
printf ("%d\n" , x);
ct[x] = 1;
for (int i = hd[x]; i; i = e[i].nt)
fans(e[i].to);
}
void tp () {
fu (i , 1 , n) vis[i] = 0;
int sum = 0;
while (sum < n) {
fu (i , 1 , n) {
if (vis[i]) continue;
if (!ru[i]) {
vis[i] = 1;
printf ("%d\n" , i);
sum ++;
for (int j = hd[i] ; j ; j = e[j].nt)
ru[e[j].to] --;
}
}
}
}
int main() {
scanf("%d%d", &n, &m);
fu(i, 1, n) {
scanf("%d%d", &t[i].f, &t[i].s);
}
int tot = 0;
fu(i, 1, n) {
tot += dfs (i);
}
printf ("%d\n" , n - tot);
fu (i , 1 , m)
if (i == t[b[i]].s)
add (b[t[b[i]].f] , b[i]);
tp ();
return 0;
}