hdu 5943 二分图匹配


注意,并不是区间上存在超过2个素数就不成立

当n > s 时 , 该条件不成立

比如数据  125 1               2361 2

事实上, 当n > s 时, 我们将s + 1 到 n 不动 , 此时只要判断 从n + 1 到 s + n 是否能成立

即转换为输入系数为 s  n 是否成立


s = 0 是特判成立会快一些

其余即二分图可解决


#include <bits/stdc++.h>


using namespace std ;
typedef long long ll ;


bool check_prime(int x){
    for(int i = 2 ; i <= sqrt(x) ; i ++ ){
        if(x % i == 0) return false ;
    }
    return true ;
}

struct Edge
{
    int from;
    int to;
    int weight;

    Edge(int f, int t, int w):from(f), to(t), weight(w) {}
};
const int __maxNodes = 100000 ;
vector<int> G[__maxNodes];
vector<Edge> edges;
typedef vector<int>::iterator iterator_t;
int num_nodes;
int num_left;
int num_right;
int num_edges;
void add_edge_value_1(int l , int r){///attention  add value is only 1
    Edge a = Edge(l , r , 1) ;
    edges.push_back(a);
    G[l].push_back(edges.size() - 1) ;
    a = Edge(r , l , 1) ;
    edges.push_back(a) ;
    G[r].push_back(edges.size() - 1) ;
}
int matching[__maxNodes];
int check[__maxNodes];

bool dfs(int u)
{
    for (iterator_t i = G[u].begin(); i != G[u].end(); ++i) {
        int v = edges[*i].to;
        if (!check[v]) {
            check[v] = true;
            if (matching[v] == -1 || dfs(matching[v])) {

                matching[v] = u;
                matching[u] = v;
                return true;
            }
        }
    }
    return false;
}

int hungarian()
{
    int ans = 0;
    memset(matching, -1, sizeof(matching));
    for (int u=1; u <= num_left; ++u) {
        if (matching[u] == -1) {
            memset(check, 0, sizeof(check));
            if (dfs(u))
                ++ans;
        }
    }
    return ans;
}
/*
3
1000000000 1000000000
125 1
2361 2
*/

int main(){
    int T ; scanf("%d" , &T) ;
    int n , k ;
    int kk = 1 ;
    while(T --){
        scanf("%d %d" , &n , &k) ;
        printf("Case #%d: " ,kk++ ) ;
        if(0 == k) { puts("Yes"); continue ; }
        int num = 0 ;
        if(n > k) swap(n , k) ;
        ///without up code , want pass the "125 1 " data 
        ///but actually , 2 to 126 can treat like this , 2 to 125 don t move , 126 puts on 1 
        ///just like if k < n , we can put k + 1 to n don t move , and question become weather n + 1 to k + n can put on the right place
        ///just become the (k , n)
        for(int i = 1 + k ; i <= n + k ; i ++ ){

            if(check_prime(i)) num ++ ;// cout << i << endl;
            if(num >= 2) break ;
        }
        //cout << num << endl ;
        if(num > 1) {puts("No") ; continue ; }
        for(int i = 0 ; i <= 1000 ; i ++ )
            G[i].clear();
        edges.clear();
        num_left = num_right = n ;
        for(int i = 1 + k ; i <= n + k ; i ++ ){
             for(int j = 1 ; j <= sqrt(i) && j <= n ; j ++ ){
                if(i % j == 0){
                    add_edge_value_1(i - k + n , j ) ;
                    //cout << i << " " << i - k + n << " " << j << endl ;
                    if(i / j != j && i / j <= n ){
                        add_edge_value_1(i - k + n , i / j ) ;
                    }
                }
             }
        }
        int ans = hungarian() ;
        //cout << ans << endl ;
        if(ans == num_left)  puts("Yes") ;
        else puts("No") ;

    }
    return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值