ccpc杭州K题(hdu5943) Kingdom of Obsession

31 篇文章 0 订阅
3 篇文章 0 订阅

首先如果s+1~s+n中有两个数是素数,那么肯定是no;也就是如果1~2e9中素数的最大距离如果是m,那当n>m时就不成立了。(其实上这有一点问题)
我直接假设m=1000,事实上m比500还要小。
那么现在问题就降为
1≤T≤100.
1≤n≤1000.
0≤s≤1e9.
那么问题就很简单了,如果s+k是某个i的倍数,那么s+k就是可能和i进行匹配(1可以和任何一个数匹配)。然后找最大匹配数是否==n-1(由于1可以和任何一个数匹配,所以把它移掉,减少边数) (二分图匹配!!!)

当时wa了,wa了。
怎么看都没敲错啊!队友说看题,突然哦,你取s=0,n=100000。纳尼,居然跑出来是no。特判呗
wa
队友:s=1也是可以的,我:特判
队友:等等,3呢 我: 哦。。。。。。
这样考虑 s+1<=n时,s+1~s+n与1~n有交叉,显然交叉的部分直接匹配就可以,那就剩n+1~s+n和1~s匹配。其实现在就相当于n和s的值换了一下。(所以此时n>500就应该改为(n>500&&s+1>n)||(s>500&&s+1<=n))
ac!

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <stack>
#include <vector>
#include <cstring>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;

const int MAXN=505;
const int inf=0x3f3f3f3f;
vector<int> G[MAXN];
int Mx[MAXN],My[MAXN];
int dx[MAXN],dy[MAXN];
int dis,n;
bool used[MAXN];
bool SearchP(void)
{
    queue<int > Q;
    dis=inf;
    msc(dx);
    msc(dy);
    for(int i=2;i<=n;i++)
        if(Mx[i]==-1){
            Q.push(i);
            dx[i]=0;
        }
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        if(dx[u]>dis) break;
        int sz=G[u].size();
        for(int i=0;i<sz;i++)
        {
            int v=G[u][i];
            if(dy[v]==-1){
                dy[v]=dx[u]+1;
                if(My[v]==-1) dis=dy[v];
                else{
                    dx[My[v]]=dy[v]+1;
                    Q.push(My[v]);
                }
            }
        }
    }
    return dis!=inf;
}
bool DFS(int u)
{
    int sz=G[u].size();
    for(int i=0;i<sz;i++)
    {
        int v=G[u][i];
        if(!used[v]&&dy[v]==dx[u]+1){
            used[v]=true;
            if(My[v]!=-1&&dy[v]==dis) continue;
            if(My[v]==-1||DFS(My[v])){
                My[v]=u;
                Mx[u]=v;
                return true;
            }
        }
    }
    return false;
}
int MaxMatch(void)
{
    int res=0;
    msc(Mx);
    msc(My);
    while(SearchP()){
        ms(used);
        for(int i=2;i<=n;i++)
            if(Mx[i]==-1&&DFS(i))
                res++;
    }
    return res;
}
int main(int argc, char const *argv[])
{   
    int t,ti=0;
    scanf("%d",&t);
    while(++ti<=t){
        int s;
        scanf("%d%d",&n,&s);
        printf("Case #%d: ",ti );
        if(s<=2) {puts("Yes");continue;}
        if((n>500&&s+1>n)||(s>500&&s+1<=n)) {puts("No");continue;}
        if(n>500) swap(n,s);
        for(int i=2;i<=n;i++)
        {
            G[i].clear();
            for(int j=s+1;j<=s+n;j++)
                if(j%i==0) G[i].push_back(j-s);
        }
        puts(MaxMatch()==n-1?"Yes":"No");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值