zoukankan      html  css  js  c++  java
  • wenbao与二分图

     -----------------------------

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

     1 #include <iostream>
     2 #include <time.h>
     3 #include <stdio.h>
     4 #include <vector>
     5 #include <string.h>
     6 using namespace std;
     7 const int maxn = 505;
     8 int n, x, y, sum;
     9 bool vis[maxn];
    10 int use[maxn];
    11 vector<int> v[maxn];
    12 bool Find(int x){
    13     for(int i = 0; i < v[x].size(); ++i){
    14         int xx = v[x][i];
    15         if(!vis[xx]){
    16             vis[xx] = true;
    17             if(!use[xx] || Find(use[xx])){
    18                 use[xx] = x;
    19                 return true;
    20             }
    21         }
    22     }
    23     return false;
    24 }
    25 int main(){
    26     while(scanf("%d", &n)){
    27         if(n == 0) break;
    28         scanf("%d%d", &x, &y);
    29         int sum = 0;
    30         memset(use, 0, sizeof(use));
    31         for(int i = 0; i < n; ++i){
    32             int xx, yy;
    33             scanf("%d%d", &xx, &yy);
    34             v[xx].push_back(yy);
    35         }
    36         for(int i = 1; i <= x; ++i){
    37             memset(vis, false, sizeof(vis));
    38             if(Find(i)) sum ++;
    39         }
    40         printf("%d
    ", sum);
    41         for(int i = 1; i <= x; ++i){
    42             v[i].clear();
    43         }
    44     }
    45     //printf("%.3lf
    ", (double)clock()/CLOCKS_PER_SEC);
    46     return 0;
    47 }

     --------------------------------------

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

    konig定理

    二分图:

    顶点可以分类两个集合X和Y,所有的边关联在两个顶点中,恰好一个属于集合X,另一个属于集合Y。

    最小覆盖:

    最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。可以证明:最少的点(即覆盖数)=最大匹配数

    Konig定理:

    二分图的最小顶点覆盖数 == 最大匹配数。

     1 #include <iostream>
     2 #include <ctime>
     3 #include <string.h>
     4 #include <vector>
     5 using namespace std;
     6 const int maxn = 109;
     7 vector<int> v[maxn];
     8 int use[maxn];
     9 bool vis[maxn];
    10 bool Find(int x){
    11     for(int i = 0; i < v[x].size(); ++i){
    12         int xx = v[x][i];
    13         if(!vis[xx]){
    14             vis[xx] = true;
    15             if(!use[xx] || Find(use[xx])){
    16                 use[xx] = x;
    17                 return true;
    18             }
    19         }
    20     }
    21     return false;
    22 }
    23 int main(){
    24     int x, y, n, m, xx, yy;
    25     while(scanf("%d", &x)){
    26         if(x == 0) break;
    27         memset(use, 0, sizeof(use));
    28         scanf("%d%d", &y, &n);
    29         for(int i = 0; i < n; ++i){
    30             scanf("%d%d%d", &m, &xx, &yy);
    31             v[xx].push_back(yy);
    32         }
    33         int sum = 0;
    34         for(int i = 1; i <= x; ++i){
    35             memset(vis, false, sizeof(vis));
    36             if(Find(i)) sum ++;// cout <<i<< "******"<<endl;
    37         }
    38         printf("%d
    ", sum);
    39         for(int i = 1; i <= x; ++i) v[i].clear();
    40     }
    41     return 0;
    42 }

     ---------------------------------------

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

    01矩阵中求最少次数变为全为0的矩阵(可以消去一行和一列)

     1 #include <iostream>
     2 #include <ctime>
     3 #include <vector>
     4 #include <string.h>
     5 using namespace std;
     6 const int maxn = 105;
     7 vector<int> v[maxn];
     8 int use[maxn];
     9 bool vis[maxn];
    10 bool Find(int x){
    11     for(int i = 0; i < v[x].size(); ++i){
    12         int xx = v[x][i];
    13         if(!vis[xx]){
    14             vis[xx] = true;
    15             if(!use[xx] || Find(use[xx])){
    16                 use[xx] = x;
    17                 return true;
    18             }
    19         }
    20     }
    21     return false;
    22 }
    23 int main(){
    24     int n, m;
    25     char x;
    26     while(~scanf("%d", &n) && n){
    27         scanf("%d", &m);
    28         for(int i = 1; i <= n; ++i){
    29             for(int j = 1; j <= m; ++j){
    30                 scanf(" %c", &x);
    31                 if(x == '1') v[i].push_back(j);
    32             }
    33         }
    34         int sum = 0;
    35         memset(use, 0, sizeof(use));
    36         for(int i = 1; i <= n; ++i){
    37             memset(vis, false, sizeof(vis));
    38             if(Find(i)) sum ++;
    39         }
    40         printf("%d
    ", sum);
    41         for(int i = 1; i <= n; ++i){
    42             v[i].clear();
    43         }
    44     }
    45     return 0;
    46 }

     ---------------------------------------------

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

    盒子套盒子

     1 #include <iostream>
     2 #include <string.h>
     3 #include <stdio.h>
     4 using namespace std;
     5 const int maxn = 505;
     6 struct Node{
     7     int x, y, z;
     8 }T[maxn];
     9 int use[maxn], n;
    10 bool vis[maxn];
    11 bool ok(int a, int b){
    12     if(T[a].x > T[b].x && T[a].y > T[b].y && T[a].z > T[b].z) return true;
    13     return false;
    14 }
    15 bool Find(int x){
    16     for(int i = 1; i <= n; ++i){
    17         if(!vis[i] && ok(x, i)){
    18             vis[i] = true;
    19             if(!use[i] || Find(use[i])){
    20                 use[i] = x;
    21                 return true;
    22             }
    23         }
    24     }
    25     return false;
    26 }
    27 int main(){
    28     while(~scanf("%d", &n) && n){
    29         for(int i = 1; i <= n; ++i){
    30             scanf("%d%d%d", &T[i].x, &T[i].y, &T[i].z);
    31         }
    32         memset(use, 0, sizeof(use));
    33         int sum = 0;
    34         for(int i = 1; i <= n; ++i){
    35             memset(vis, false, sizeof(vis));
    36             if(Find(i)) sum ++;
    37         }
    38         printf("%d
    ", n-sum);
    39     }
    40     return 0;
    41 }

     ----------------------------------------

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

     带权并查集

     1 #include <iostream>
     2 #include <string.h>
     3 #include <vector>
     4 using namespace std;
     5 const int maxn = 100009;
     6 int T[maxn], sum[maxn], a[maxn], b[maxn][2];
     7 bool vis[maxn];
     8 int Find(int x){
     9     if(x == T[x]) return x;
    10     int xx = T[x];
    11     T[x] = Find(xx);
    12     sum[x] ^= sum[xx];
    13     return T[x];
    14 }
    15 int main(){
    16     int t;
    17     scanf("%d", &t);
    18     while(t--){
    19         bool flag = true;
    20         int n, m;
    21         scanf("%d%d", &n, &m);
    22         for(int i = 1; i <= n; ++i){
    23             T[i] = i, sum[i] = 0;
    24         }
    25         for(int i = 0; i < m; ++i){
    26             int x, y;
    27             scanf("%d%d", &x, &y);
    28             int xx = Find(x), yy = Find(y);
    29             if(xx != yy){
    30                 T[yy] = xx;
    31                 sum[yy] = sum[x]^1^sum[y];
    32             }else{
    33                 if(sum[x] == sum[y]){
    34                     flag = false;
    35                 }
    36             }
    37         }
    38         if(!flag || n <= 1){
    39             printf("Poor wyh
    ");
    40             continue;
    41         }
    42         if(m == 0){
    43             printf("%d 1
    ", n-1);
    44             continue;
    45         }
    46         int num = 0, mi = 0;
    47         memset(vis, false, sizeof(vis));
    48         memset(b, 0, sizeof(b));
    49         for(int i = 1; i <= n; ++i){
    50             int xx = Find(i);
    51             //printf("%d*******%d
    ", xx, sum[i]);
    52             if(!vis[xx]){
    53                 vis[xx] = true;
    54                 a[num++] = xx;
    55             }
    56             b[xx][sum[i]] ++;
    57         }
    58         for(int i = 0; i < num; ++i){
    59             int xx = a[i];
    60             mi += min(b[xx][0], b[xx][1]);
    61             //cout<<xx<<"***"<<b[xx][0]<<"****"<<b[xx][1]<<endl;
    62         }
    63         printf("%d %d
    ", n-mi, mi);
    64     }
    65     return 0;
    66 }
    67 
    68 
    69 /*
    70 5 3
    71 1 2
    72 1 3
    73 1 4
    74 */

    dfs标记染色

     1 #include <iostream>
     2 #include <vector>
     3 #include <queue>
     4 #include <string.h>
     5 using namespace std;
     6 const int maxn = 100009;
     7 vector<int> v[maxn];
     8 int num, num2, vis[maxn];
     9 bool dfs(int x){
    10     if(v[x].size() == 0) return true;
    11     queue<int> q;
    12     q.push(x);
    13     vis[x] = 1;
    14     while(!q.empty()){
    15         int y = q.front();
    16         q.pop();
    17         for(int i = 0; i < v[y].size(); ++i){
    18             int xx = v[y][i];
    19             if(vis[y] == vis[xx]) return false;
    20             if(!vis[xx]){
    21                 vis[xx] = vis[y] == 1 ? 2 : 1;
    22                 q.push(xx);
    23                 if(vis[xx] == 1) num ++;
    24                 else num2 ++;
    25             }
    26         }
    27     }
    28     return true;
    29 }
    30 int main(){
    31     int t;
    32     scanf("%d", &t);
    33     while(t--){
    34         int n, m, mi = 0;
    35         scanf("%d%d", &n, &m);
    36         for(int i = 0; i < m; ++i){
    37             int x, y;
    38             scanf("%d%d", &x, &y);
    39             v[x].push_back(y), v[y].push_back(x);
    40         }
    41         if(n <= 1){
    42             printf("Poor wyh
    ");
    43             continue;
    44         }
    45         if(m == 0){
    46             printf("%d 1
    ", n-1);
    47             continue;
    48         }
    49         bool flag = true;
    50         memset(vis, 0, sizeof(vis));
    51         for(int i = 1; i <= n; ++i){
    52             if(!vis[i]){
    53                 num = 1, num2 = 0;
    54                 if(!dfs(i)){
    55                     flag = false;
    56                     break;
    57                 }
    58                 mi += max(num, num2);
    59             }
    60         }
    61         if(!flag){
    62             printf("Poor wyh
    ");
    63         }else{
    64             printf("%d %d
    ", mi, n-mi);
    65         }
    66         for(int i = 1; i <= n; ++i) v[i].clear();
    67     }
    68     return 0;
    69 }

    -----------------------------------------------

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

    判断二分图再求最大匹配

    并查集判断二分图

     1 #include <iostream>
     2 #include <string.h>
     3 #include <vector>
     4 using namespace std;
     5 const int maxn = 205;
     6 vector<int> v[maxn];
     7 int sum[maxn], T[maxn], use[maxn];
     8 bool vis[maxn];
     9 bool FFind(int x){
    10     for(int i = 0; i < v[x].size(); ++i){
    11         int xx = v[x][i];
    12         if(!vis[xx]){
    13             vis[xx] = true;
    14             if(!use[xx] || FFind(use[xx])){
    15                 use[xx] = x;
    16                 return true;
    17             }
    18         }
    19     }
    20     return false;
    21 }
    22 int Find(int x){
    23     if(T[x] == x) return x;
    24     int xx = T[x];
    25     T[x] = Find(xx);
    26     sum[x] ^= sum[xx];
    27     return T[x];
    28 }
    29 int main(){
    30     int n, m;
    31     while(~scanf("%d%d", &n, &m)){
    32         for(int i = 1; i <= n; ++i) T[i] = i, sum[i] = 0, v[i].clear();
    33         bool flag = true;
    34         for(int i = 0; i < m; ++i){
    35             int x, y;
    36             scanf("%d%d", &x, &y);
    37             if(!flag) continue;
    38             int xx = Find(x), yy = Find(y);
    39             if(xx != yy){
    40                 T[xx] = yy;
    41                 sum[xx] = sum[x] ^ sum[y] ^ 1;
    42             }else{
    43                 if(sum[x] == sum[y]){
    44                     flag = false;
    45                 }
    46             }
    47             v[x].push_back(y);
    48         }
    49         if(!flag) printf("No
    ");
    50         else{
    51             memset(use, 0, sizeof(use));
    52             int sum = 0;
    53             for(int i = 1; i <= n; ++i){
    54                 memset(vis, false, sizeof(vis));
    55                 if(FFind(i)) sum ++;
    56             }
    57             printf("%d
    ", sum);
    58         }
    59     }
    60     return 0;
    61 }

    染色判断二分图

     1 #include <iostream>
     2 #include <string.h>
     3 #include <vector>
     4 #include <queue>
     5 using namespace std;
     6 const int maxn = 205;
     7 vector<int> v[maxn];
     8 int vis[maxn], num, num2, use[maxn];
     9 bool vi[maxn];
    10 bool Find(int x){
    11     for(int i = 0; i < v[x].size(); ++i){
    12         int xx = v[x][i];
    13         if(!vi[xx]){
    14             vi[xx] = true;
    15             if(!use[xx] || Find(use[xx])){
    16                 use[xx] = x;
    17                 return true;
    18             }
    19         }
    20     }
    21     return false;
    22 }
    23 bool dfs(int x){
    24     queue<int> q;
    25     q.push(x);
    26     vis[x] = 1;
    27     while(!q.empty()){
    28         int y = q.front();
    29         q.pop();
    30         for(int i = 0; i < v[y].size(); ++i){
    31             int xx = v[y][i];
    32             if(vis[xx] == vis[y]) return false;
    33             if(!vis[xx]){
    34                 vis[xx] = vis[y] == 1 ? 2 : 1;
    35                 if(vis[xx] == 1) num ++;
    36                 else num2 ++;
    37                 q.push(xx);
    38             }
    39         }
    40     }
    41     return true;
    42 }
    43 int main(){
    44     int n, m;
    45     while(~scanf("%d%d", &n, &m)){
    46         for(int i = 1; i <= n; ++i) v[i].clear();
    47         for(int i = 0; i < m; ++i){
    48             int x, y;
    49             scanf("%d%d", &x, &y);
    50             v[x].push_back(y), v[y].push_back(x);
    51         }
    52         if(m == 0){
    53             printf("0
    ");
    54             continue;
    55         }
    56         bool flag = true;
    57         memset(vis, 0, sizeof(vis));
    58         int ma = 0;
    59         for(int i = 1; i <= n; ++i){
    60             if(!vis[i] && v[i].size() != 0){
    61                 num = 1, num2 = 0;
    62                 if(!dfs(i)){
    63                     flag = false;
    64                     break;
    65                 }
    66             }
    67         }
    68         if(!flag) printf("No
    ");
    69         else{
    70             memset(use, 0, sizeof(use));
    71             int sum = 0;
    72             for(int i = 1; i <= n; ++i){
    73                 memset(vi, false, sizeof(vi));
    74                 if(Find(i)) sum ++;
    75             }
    76             printf("%d
    ", sum/2);
    77         }
    78     }
    79     return 0;
    80 }

    ----------------------------------------------------------

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

    染色

     1 #include <iostream>
     2 #include <queue>
     3 #include <string.h>
     4 #include <vector>
     5 using namespace std;
     6 const int maxn = 100009;
     7 int vis[maxn], n, m, s;
     8 vector<int> v[maxn];
     9 bool dfs(int x){
    10     memset(vis, 0, sizeof(vis));
    11     queue<int> q;
    12     q.push(x);
    13     vis[x] = 1;
    14     int num = 1;
    15     bool flag = false;
    16     while(!q.empty()){
    17         int xx = q.front();
    18         //cout<<"%%%%%%%%%%%"<<xx<<endl;
    19         q.pop();
    20         for(int i = 0; i < v[xx].size(); ++i){
    21             int xxx = v[xx][i];
    22             if(vis[xx] == vis[xxx]){
    23                 //cout<<xx<<"****"<<xxx<<"***"<<vis[xx]<<endl;
    24                 flag = true;
    25             }
    26             if(!vis[xxx]){
    27                 vis[xxx] = vis[xx] == 1 ? 2 : 1;
    28                 num++;
    29                 q.push(xxx);
    30             }
    31         }
    32     }
    33     //cout<<num<<"****"<<endl;
    34     if(flag && num == n) return true;
    35     else return false;
    36 }
    37 int main(){
    38     int t;
    39     scanf("%d", &t);
    40     for(int j = 1; j <= t; ++j){
    41         scanf("%d%d%d", &n, &m, &s);
    42         for(int i = 0; i < n; ++i) v[i].clear();
    43         for(int i = 0; i < m; ++i){
    44             int x, y;
    45             scanf("%d%d", &x, &y);
    46             v[x].push_back(y), v[y].push_back(x);
    47         }
    48         if(dfs(s)){
    49             printf("Case %d: YES
    ", j);
    50         }else{
    51             printf("Case %d: NO
    ", j);
    52         }
    53     }
    54     return 0;
    55 }

    --------------------------------------------------

    https://loj.ac/problem/526

    从n个树中选择最大子集满足任意两个数x,y gcd(x,y)*gcd(x+1, y+1) != 1,易知同奇同偶一定满足,然后奇偶建边,求最大独立集,除去最大独立集就是所求

     1 #include <iostream>
     2 #include <vector>
     3 #include <string.h>
     4 using namespace std;
     5 
     6 #define ll long long
     7 ll a[555];
     8 vector<int> v[555];
     9 int use[555];
    10 bool vis[555];
    11 
    12 ll g(ll x, ll y){
    13     return y ? g(y, x%y) : x;
    14 }
    15 
    16 bool d(int x){
    17     for(int i = 0; i < v[x].size(); ++i){
    18         int xx = v[x][i];
    19         if(!vis[xx]){
    20             vis[xx] = true;
    21             if(!use[xx] || d(use[xx])){
    22                 use[xx] = x;
    23                 return true;
    24             }
    25         } 
    26     }
    27     return false;
    28 }
    29 
    30 int main(){
    31     int n;
    32     scanf("%d", &n);
    33     for(int i = 1; i <= n; ++i){
    34         scanf("%lld", &a[i]);
    35     }
    36     for(int i = 1; i <= n; ++i) if(a[i]&1){
    37         for(int j = 1; j <= n; ++j) if(!(a[j]&1)){
    38             if(g(a[i], a[j]) == 1 && g(a[i]+1, a[j]+1) == 1) v[i].push_back(j);
    39         }
    40     }
    41     int num = 0;
    42     for(int i = 1; i <= n; ++i) if(a[i]&1){
    43         memset(vis, false, sizeof(vis));
    44         if(d(i)) num++;
    45     }
    46     printf("%d
    ", n-num);
    47     return 0;
    48 }

    --------------------------------------------------

    只有不断学习才能进步!

  • 相关阅读:
    openldap---ldapsearch使用
    自旋锁与相互排斥锁之抉择
    探索Android中的Parcel机制(上)
    我的Android开发相关文章
    SoftReference
    Windows7WithSP1/TeamFoundationServer2012update4/SQLServer2012
    机器学习中规则化和模型选择知识
    Java中System的详细用法
    Java中System的详细用法
    Java中System的详细用法
  • 原文地址:https://www.cnblogs.com/wenbao/p/6478739.html
Copyright © 2011-2022 走看看