HDU 5943 - Kingdom of Obsession(二分图匹配)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5943
【题意】
给定n,s,现在让1-n和s+1,s+2...s+n这两堆数匹配,如果(s+i)%j==0那么s+i就可以和j构成一个匹配,求是否能让所有的n个
数字都构成匹配。(n, s <= 1e9)
【思路】
首先,如果1-n这n个数中出现了素数那么就一定无法让所有数字都匹配,而2e9以内的数字里面,最大的素数间隔不超过300,
这是一个很关键的结论,所以当n很大时直接输出"No"即可。当n比较小时,变成了一个二分匹配的问题,用匈牙利算法实现。
判断是否能够全部匹配即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1050;
int n, s;
int used[maxn];
int link[maxn];
int g[maxn][maxn];
bool find(int x) {
for (int i = 1; i <= n; ++i) {
if (!used[i] && g[x][i] == 1) {
used[i] = 1;
if (link[i] == 0 || find(link[i])) {
link[i] = x;
return 1;
}
}
}
return 0;
}
int main() {
int t;
scanf("%d", &t);
for (int kase = 1; kase <= t; ++kase) {
scanf("%d%d", &n, &s);
printf("Case #%d: ", kase);
if (n > s) swap(n, s);
if (n > 1000) {
printf("No\n");
continue;
}
memset(g, 0, sizeof(g));
for (int i = 1; i <= n; ++i) {
int tmp = s + i;
for (int j = 1; j <= n; ++j)
if (tmp % j == 0) g[i][j] = 1;
}
memset(link, 0, sizeof(link));
int ans = 0;
for (int i = 1; i <= n; ++i) {
memset(used, 0, sizeof(used));
if (find(i)) ++ans;
}
printf("%s\n", ans == n ? "Yes" : "No");
}
return 0;
}