hdu 5943 二分图匹配

来源:互联网 发布:完美dota2 有mac版 编辑:程序博客网 时间:2024/05/21 17:09


注意,并不是区间上存在超过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;}/*31000000000 1000000000125 12361 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 ;}