HDU 5943 Kingdom of Obsession(二分图)

来源:互联网 发布:mac软件推荐 编辑:程序博客网 时间:2024/06/11 05:08

http://acm.hdu.edu.cn/showproblem.php?pid=5943

题意:你有n个数字,他们分别从s+1到s+n,将他们打乱,问是否可以整除1到n。

解法:很明显,如果s+1到s+n有两个素数则无解。但是如果慢慢去求这个区间是否有两个素数也很费时间。百度一下发现,五亿以内最大的素数间隔好像是280多,那么两个素数就是600多吧。。。也就是n大于600就会有两个素数,如果小于600就可以用二分图匹配一下看看。

但是,还没这么简单。一大问题,就是区间可能是重复的,如果1到n和s+1到s+n有重复,因为已经是1到n重复了,他们已经是最小的一批因子了,他们肯定是一一对应的。所以我们就拿出1到s和n+1到s+n来二分图匹配一下,看看这一段是否可以匹配。

还有就是,如果s==0,那么肯定是匹配的。

代码如下:

#include<bits/stdc++.h>using namespace std;const int MAXN = 605;int n, s;int uN, vN;  //u,v数目bool G[MAXN][MAXN];//编号是0~n-1的 int linker[MAXN];bool used[MAXN];bool dfs(int u){    int v;    for(v = 0; v < vN; v++)        if(G[u][v] && !used[v])        {            used[v] = true;            if(linker[v] == -1 || dfs(linker[v]))            {                linker[v] = u;                return true;            }            }      return false;  }    int hungary(){    int res = 0;    int u;    memset(linker, -1, sizeof(linker));    for(u = 0; u < uN; u++)    {        memset(used, 0, sizeof(used));        if(dfs(u))  res++;    }     return res;   }     void build() {int tmp;for(int i = 1; i <= n; i++) {tmp = s + i;for(int j = 1; j <= n; j++) {if(tmp % j == 0) {G[i - 1][j - 1] = 1;}}}}int main(){int T, Case = 1;cin >> T;while(T--) {cin >> n >> s;if(s < n) {if(s + n - n > 600) {printf("Case #%d: No\n", Case++);} else {memset(G, 0, sizeof(bool) * MAXN * MAXN);int tmp = s;s = n;n = tmp;build();tmp = hungary();if(tmp == n)printf("Case #%d: Yes\n", Case++);elseprintf("Case #%d: No\n", Case++);}}else if(n > 600)printf("Case #%d: No\n", Case++);else {memset(G, 0, sizeof(bool) * MAXN * MAXN);uN = vN = n;build();int ans = hungary();if(ans == n)printf("Case #%d: Yes\n", Case++);elseprintf("Case #%d: No\n", Case++);}}return 0;}


阅读全文
0 0