• 二分图'多重匹配'


    // 模板。(匈牙利的稍微改写) 和 例题(最下面) 一般多重匹配需要配合二分查找答案

    // 例题 :hdu 3605

    // 题意:有n(n <= 100000)个人和m(m <= 10)个星球,  每个人有自己想去的星球(不止一个), 但每个星球能承受的人数不同。问: 能不能把所有人安排到他自己想去的星球上;

    // 输入(机翻): 

     //输出 YES or NO

     1 #include<iostream>
     2 #define read(n) n = read_n()
     3 #define rep(i, n) for(int i=0;i!=n;++i)
     4 #define rep1(i, n) for(int i=1;i<=n;++i)
     5 using namespace std;
     6 
     7 inline int read_n() {
     8     char c=getchar();int x=0,f=1;
     9     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    10     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    11     return x*f;
    12 }
    13 // -----------------------------------------------------
    14 const int MAXN = 100000+5;
    15 const int MAXM = 10+5;
    16 const int MAXE = MAXN*MAXM;
    17 
    18 int num;
    19 int head[MAXN];
    20 struct node {
    21     int v, next;
    22 } edge[MAXE];
    23 
    24 inline void add(int x, int y) {
    25     edge[num].v = y;
    26     edge[num].next = head[x];
    27     head[x] = num++;
    28 }
    29 
    30 int n, m;
    31 int maxn[MAXM];
    32 
    33 int cnt[MAXM];
    34 int love[MAXM][MAXN];// love[i][j]表示i星球的第j位置匹配到了某人
    35 bool vis[MAXM];
    36 // -----------------核心----------------------
    37 bool dfs(int u) {
    38     for(int i = head[u]; i != -1; i = edge[i].next) {
    39         int v = edge[i].v;
    40         if(!vis[v]) {
    41             vis[v] = true;
    42             if(cnt[v] < maxn[v]) {// 如果v还有"位置"匹配
    43                 love[v][++cnt[v]] = u;
    44                 return true;
    45             }
    46             for(int j = 1; j <= cnt[v]; ++j) {// 若没有位置了, 从已经匹配的上面找是否有人能腾出位置
    47                 if(dfs(love[v][j])) {
    48                     love[v][j] = u;
    49                     return true;
    50                 }
    51             }
    52         }
    53     }
    54     return false;
    55 }
    56 // ---------------------------------------------
    57 bool solve() {
    58     rep1(i, m) cnt[i] = 0;
    59     rep1(i, n) {
    60         rep1(j, m) vis[j] = false;
    61         if(!dfs(i)) return false;
    62     }
    63     return true;
    64 }
    65 
    66 int main() {
    67     while(cin >> n >> m) {
    68         num = 0;
    69         rep1(i, n) head[i] = -1;
    70         int x;
    71         rep1(i, n) rep1(j, m) {
    72             read(x);
    73             if(x == 1) add(i, j);
    74         }
    75         rep1(i, m) read(maxn[i]);
    76         if(solve()) cout << "YES
    ";
    77         else cout << "NO
    ";
    78     }
    79     return 0;
    80 }

     // poj 2289 二分查找答案

     1 #include<iostream>
     2 #include<sstream>
     3 #include<cstdlib>
     4 using namespace std;
     5 
     6 const int MAXN = 1000+5;
     7 const int MAXM = 500+5;
     8 const int MAXE = MAXN*MAXM;
     9 
    10 int num;
    11 int head[MAXN];
    12 struct node {
    13     int v, next;
    14 } edge[MAXE];
    15 
    16 inline void add(int x, int y) {
    17     edge[num].v = y;
    18     edge[num].next = head[x];
    19     head[x] = num++;
    20 }
    21 
    22 int n, m, maxn;
    23 string str;
    24 
    25 int cnt[MAXN];
    26 int love[MAXN][MAXM];
    27 bool vis[MAXN];
    28 
    29 bool dfs(int u) {
    30     for(int i = head[u]; i != -1; i = edge[i].next) {
    31         int v = edge[i].v;
    32         if(!vis[v]) {
    33             vis[v] = true;
    34             if(cnt[v] < maxn) {
    35                 love[v][++cnt[v]] = u;
    36                 return true;
    37             }
    38             for(int j = 1; j <= cnt[v]; ++j) {
    39                 if(dfs(love[v][j])) {
    40                     love[v][j] = u;
    41                     return true;
    42                 }
    43             }
    44         }
    45     }
    46     return false;
    47 }
    48 
    49 bool hungry(int p) {
    50     maxn = p;
    51     for(int i = 0; i != m; ++i) cnt[i] = 0;
    52     for(int i = 1; i <= n; ++i) {
    53         for(int j = 0; j != m; ++j) vis[j] = false;
    54         if(!dfs(i)) return false;
    55     }
    56     return true;
    57 }
    58 
    59 int main() {
    60     ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    61     while(cin >> n >> m && n) {
    62         num = 0;
    63         getchar();
    64         for(int i = 1; i <= n; ++i) head[i] = -1;
    65         for(int i = 1; i <= n; ++i) {
    66             getline(cin, str);
    67             stringstream s(str);
    68             string ss;
    69             while(s >> ss) {
    70                 if(isalpha(ss[0])) continue;
    71                 int p = atoi(ss.c_str());
    72                 add(i, p);
    73             }
    74         }
    75         int l = 1, r = n, mid, ans;
    76         while(l <= r) {
    77             mid = (l+r)/2;
    78             if(hungry(mid)) ans = mid, r = mid - 1;
    79             else l = mid + 1;
    80         }
    81         cout << ans << "
    ";
    82     }
    83     return 0;
    84 }
    View Code

    // poj 2112 二分查找答案

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<vector>
     4 #define rep(i, n) for(int i=0;i!=n;++i)
     5 #define rep1(i, n) for(int i=1;i<=n;++i)
     6 #define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
     7 using namespace std;
     8 // -----------------------------------------------------
     9 const int MAXN = 230+5;
    10 const int MAXE = MAXN*MAXN;
    11 
    12 int num;
    13 int head[MAXN];
    14 struct node {
    15     int v, next;
    16 } edge[MAXE];
    17 
    18 inline void add(int x, int y) {
    19     edge[num].v = y;
    20     edge[num].next = head[x];
    21     head[x] = num++;
    22 }
    23 
    24 int n, m, nm, maxn, dis;
    25 int G[MAXN][MAXN];
    26 
    27 int cnt[MAXN];
    28 int love[MAXN][MAXN];
    29 bool vis[MAXN];
    30 
    31 bool dfs(int u) {
    32     for(int i = head[u]; i != -1; i = edge[i].next) {
    33         int v = edge[i].v;
    34         if(G[u][v] > dis) continue;
    35         if(!vis[v]) {
    36             vis[v] = true;
    37             if(cnt[v] < maxn) {
    38                 love[v][++cnt[v]] = u;
    39                 return true;
    40             }
    41             for(int j = 1; j <= cnt[v]; ++j) {
    42                 if(dfs(love[v][j])) {
    43                     love[v][j] = u;
    44                     return true;
    45                 }
    46             }
    47         }
    48     }
    49     return false;
    50 }
    51 
    52 bool solve(int d) {
    53     dis = d;
    54     rep1(i, m) cnt[i] = 0;
    55     Rep1(i, m+1, nm) {
    56         rep1(j, m) vis[j] = false;
    57         if(!dfs(i)) return false;
    58     }
    59     return true;
    60 }
    61 
    62 int main() {
    63     ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    64     cin >> m >> n >> maxn;
    65     nm = n+m;
    66     num = 0;
    67     rep1(i, nm) head[i] = -1;
    68     rep1(i, nm) rep1(j, nm) cin >> G[i][j];
    69     rep1(k, nm) {
    70         rep1(i, nm) {
    71             if(G[i][k]) rep1(j, nm) if(G[k][j]) if(!G[i][j] || G[i][k]+G[k][j] < G[i][j]) {
    72                 G[i][j] = G[i][k] + G[k][j];
    73             }
    74         }
    75     }
    76     vector<int> v;
    77     Rep1(i, m+1, nm) {
    78         Rep1(j, 1, m) if(G[i][j]) add(i, j), v.push_back(G[i][j]);
    79     }
    80     sort(v.begin(), v.end());
    81     int l = 0, r = unique(v.begin(), v.end()) - v.begin()-1;
    82     int mi, ans;
    83     while(l <= r) {
    84         mi = (l+r)>>1;
    85         if(solve(v[mi])) ans = v[mi], r = mi-1;
    86         else l = mi+1;
    87     }
    88     cout << ans << "
    ";
    89     return 0;
    90 }
    View Code

    // poj 3189 二分+枚举约束条件找答案

     1 /*
     2  * @Promlem: 
     3  * @Time Limit: ms
     4  * @Memory Limit: k
     5  * @Author: pupil-XJ
     6  * @Date: 2019-11-04 23:50:39
     7  * @LastEditTime: 2019-11-05 00:27:17
     8  */
     9 #include<cstdio>
    10 using namespace std;
    11 const int MAXN = 1000+5;
    12 const int MAXM = 20+5;
    13 const int MAXE = MAXN*MAXM;
    14 
    15 int num;
    16 int head[MAXN];
    17 struct node {
    18     int v, w, next;
    19 } edge[MAXE];
    20 
    21 inline void add(int x, int y, int w) {
    22     edge[num].v = y;
    23     edge[num].w = w;
    24     edge[num].next = head[x];
    25     head[x] = num++;
    26 }
    27 
    28 int n, m;
    29 int G[MAXN][MAXM];
    30 int maxn[MAXM];
    31 
    32 int cnt[MAXM];
    33 int love[MAXM][MAXN];
    34 bool vis[MAXM];
    35 
    36 bool dfs(int u, int l, int r) {
    37     for(int i = head[u]; i != -1; i = edge[i].next) {
    38         int v = edge[i].v;
    39         if(edge[i].w < l || edge[i].w > r) continue;
    40         if(!vis[v]) {
    41             vis[v] = true;
    42             if(cnt[v] < maxn[v]) {
    43                 love[v][++cnt[v]] = u;
    44                 return true;
    45             }
    46             for(int j = 1; j <= cnt[v]; ++j) {
    47                 if(dfs(love[v][j], l, r)) {
    48                     love[v][j] = u;
    49                     return true;
    50                 }
    51             }
    52         }
    53     }
    54     return false;
    55 }
    56 
    57 bool solve(int l, int r) {
    58     for(int i = 1; i <= m; ++i) cnt[i] = 0;
    59     for(int i = 1; i <= n; ++i) {
    60         for(int j = 1; j <= m; ++j) vis[j] = false;
    61         if(!dfs(i, l, r)) return false;
    62     }
    63     return true;
    64 }
    65 
    66 int main() {
    67     scanf("%d%d", &n, &m);
    68     num = 0;
    69     for(int i = 1; i <= n; ++i) head[i] = -1;
    70     for(int i = 1; i <= n; ++i) {
    71         for(int j = 1; j <= m; ++j) {
    72             scanf("%d", &G[i][j]);
    73             add(i, G[i][j], j);
    74         }
    75     }
    76     for(int i = 1; i <= m; ++i) scanf("%d", &maxn[i]);
    77     int l = 1, r = m;
    78     int mid, ans;
    79     while(l <= r) {
    80         bool flag = false;
    81         mid = (l+r)>>1;
    82         for(int i = 1; i+mid-1<=m; ++i) {
    83             if(solve(i, i+mid-1)) ans = mid, flag = true;
    84             if(flag) break;
    85         }
    86         if(flag) r = mid-1;
    87         else l = mid+1;
    88     }
    89     printf("%d
    ", ans);
    90     return 0;
    91 }
    View Code
  • 相关阅读:
    Hibernate的一些操作
    工作心得
    放款流程
    关于C#事件的自我构想和学习
    委托之winForm窗口间传递数据
    C#中string[]数组和list<string>泛型的相互转换 【转】
    关于注册界面中的一些规则设计时要注意
    系统界面设计---风格
    关于系统注册,做卡号重校验
    关于系统设计中的硬件开发
  • 原文地址:https://www.cnblogs.com/pupil-xj/p/11792505.html
Copyright © 2020-2023  润新知