POJ 2289 Jamie's Contact Groups & POJ3189 Steady Cow Assignment

这两道题目都是多重二分匹配+枚举的做法,或者可以用网络流,实际上二分匹配也就实质是网络流,通过枚举区间,然后建立相应的图,判断该区间是否符合要求,并进一步缩小范围,直到求出解。不同之处在对是否满足条件的判断,可以求最大流或者最大匹配看匹配数目是否满足题意。

POJ 2289:

多重二分匹配:360ms

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <climits>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cmath>
 7 #include <vector>
 8 #include <queue>
 9 #include <algorithm>
10 #define esp 1e-6
11 #define pb push_back
12 #define in  freopen("in.txt", "r", stdin);
13 #define out freopen("out.txt", "w", stdout);
14 #define print(a) printf("%d
",(a));
15 #define bug puts("********))))))");
16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
17 #define inf 0x0f0f0f0f
18 using namespace std;
19 typedef long long  LL;
20 typedef vector<int> VI;
21 typedef vector<int>:: iterator IT;
22 #define N 1111
23 #define M 555
24 int n, m;
25 bool use[M];
26 int link[M][N], cap[M];
27 VI g[N];
28 bool dfs(int x)
29 {
30     int t;
31     for(int i = 0; i < (int)g[x].size(); i++)
32         if(!use[t = g[x][i]])
33         {
34             use[t] = true;
35              if(link[t][0] < cap[t])
36                 return link[t][++link[t][0]] = x, true;
37             else
38             {
39                 for(int j = 1; j <= cap[t]; j++)
40                 {
41 //                    use[t] = true;
42                     if(dfs(link[t][j]))
43                         return link[t][j] = x, true;
44                 }
45             }
46         }
47     return false;
48 }
49 bool match(void)
50 {
51     memset(link, 0, sizeof(link));
52     for(int i = 1; i <= n; i++)
53     {
54         memset(use, 0, sizeof(use));
55         if(!dfs(i))
56             return false;
57     }
58     return true;
59 }
60 void update(int mid)
61 {
62     for(int i = 1; i <= m; i++)
63         cap[i] = mid;
64 }
65 int main(void)
66 {
67     while(scanf("%d%d", &n, &m), n)
68     {
69 //        for(int i = 1; i )
70         char ch;
71         for(int i = 1; i <= n; i++)
72         {
73             g[i].clear();
74             scanf("%*s%c", &ch);
75             while(ch != '
')
76             {
77                 int k;
78                 scanf("%d%c", &k, &ch);
79                 g[i].pb(k+1);
80             }
81         }
82         int l = 1, r = n, mid;
83         int ans = n;
84         while(l <= r)
85         {
86             mid = (l+r)>> 1;
87             update(mid);
88             if(match())
89             {
90                 ans = min(mid, ans);
91                 r = mid-1;
92             }
93             else l = mid+1;
94         }
95         printf("%d
", ans);
96     }
97     return 0;
98 }

网络流:589ms

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <climits>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <vector>
  8 #include <queue>
  9 #include <algorithm>
 10 #define esp 1e-6
 11 #define pb push_back
 12 #define in  freopen("in.txt", "r", stdin);
 13 #define out freopen("out.txt", "w", stdout);
 14 #define print(a) printf("%d
",(a));
 15 #define bug puts("********))))))");
 16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
 17 #define inf 0x0f0f0f0f
 18 using namespace std;
 19 typedef long long  LL;
 20 typedef vector<int> VI;
 21 typedef vector<int>:: iterator IT;
 22 #define N 5000
 23 #define M 600000
 24 struct EDGE
 25 {
 26     int i, c;
 27     EDGE *next, *ani;
 28 } *Edge[N], E[M << 1], BE[M << 1], *tag[N];
 29 int Dfn[N], Now[N], cnt;
 30 int n, m, src, sink, ndot;
 31 
 32 void init(void)
 33 {
 34     cnt = 0;
 35     memset(Edge, 0, sizeof(Edge));
 36     src = 0, sink = 1;
 37     ndot = 2*n+2*m+2;
 38 }
 39 void add(int i, int j, int c, EDGE &e1, EDGE  &e2)
 40 {
 41     e1.i = j, e1.c = c, e1.next = Edge[i], e1.ani = &e2, Edge[i] = &e1;
 42     e2.i = i, e2.c = 0, e2.next = Edge[j], e2.ani = &e1, Edge[j] = &e2;
 43     BE[cnt] = E[cnt], BE[cnt + 1] = E[cnt + 1];
 44     cnt += 2;
 45 }
 46 int ISAP(int s, int end, int flow)
 47 {
 48     if(s == end)
 49         return flow;
 50     int i, now = 0, vary, tab = ndot - 1;
 51     for(EDGE *p = Edge[s]; p && flow; p = p->next)
 52         if(p->c)
 53         {
 54 //            bug
 55             if(Dfn[s] == Dfn[i = p->i] + 1)
 56                 vary = ISAP(i, end, min(p->c, flow)),
 57                 p->c -= vary, p->ani->c += vary, now += vary, flow -= vary;
 58             if(p->c)
 59                 tab = min(tab, Dfn[i]);
 60             if(Dfn[src] == ndot)
 61                 return now;
 62         }
 63     if(now == 0)
 64     {
 65         if(--Now[Dfn[s]] == 0)
 66             Dfn[src] = ndot;
 67         Now[Dfn[s] = tab +1]++;
 68     }
 69 //    print(now);
 70     return now;
 71 }
 72 int max_flow(int s, int end)
 73 {
 74     memset(Dfn, 0, sizeof(Dfn));
 75     memset(Now, 0, sizeof(Now));
 76     Now[0] = ndot;
 77     int ret = 0;
 78     for(; Dfn[s] < ndot;)
 79     {
 80         ret += ISAP(s, end, inf);
 81     }
 82     return ret;
 83 }
 84 void Restore(void)
 85 {
 86     for(int i = 0; i < cnt; i++)
 87         E[i] = BE[i];
 88 }
 89 void update(int c)
 90 {
 91     Restore();
 92     for(int i = n+1; i <= n+m; i++)
 93     {
 94         tag[2*i]->c = c;
 95     }
 96 }
 97 int main(void)
 98 {
 99     while(scanf("%d%d", &n, &m), n)
100     {
101 
102         char ch;
103         init();
104         for(int i = 1; i <= n; i++)
105         {
106             scanf("%*s%c", &ch);
107             while(ch != '
')
108             {
109                 int k;
110                 scanf("%d%c", &k, &ch);
111                 k += n+1;
112                 add(2*i^1, 2*k, 1, E[cnt], E[cnt + 1]);
113             }
114             add(2*i, 2*i^1, 1, E[cnt], E[cnt + 1]);
115             add(src, 2*i, 1, E[cnt], E[cnt + 1]);
116         }
117         for(int i = 1; i <= m; i++)
118         {
119             add(2*(i+n), 2*(i+n)^1, inf, E[cnt], E[cnt + 1]);
120             tag[2*(i+n)] = &E[cnt];
121             add(2*(i+n)^1, sink, inf, E[cnt], E[cnt + 1]);
122         }
123         int l = 1, r = n, mid;
124         int ans = n;
125         while(l <= r)
126         {
127             mid = (l+r)>> 1;
128             update(mid);
129             if(max_flow(src, sink) == n)
130             {
131 //                bug
132                 ans = min(mid, ans);
133                 r = mid-1;
134             }
135             else l = mid+1;
136         }
137         printf("%d
", ans);
138     }
139     return 0;
140 }

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

POJ 3189:

多重二分匹配:32ms

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <climits>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cmath>
 7 #include <vector>
 8 #include <queue>
 9 #include <algorithm>
10 #define esp 1e-6
11 #define pb push_back
12 #define in  freopen("in.txt", "r", stdin);
13 #define out freopen("out.txt", "w", stdout);
14 #define print(a) printf("%d
",(a));
15 #define bug puts("********))))))");
16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
17 #define inf 0x3f3f3f3f
18 using namespace std;
19 typedef long long  LL;
20 typedef vector<int> VI;
21 typedef vector<int>:: iterator IT;
22 #define N 30
23 #define M 1111
24 int n, m, mx, mi;
25 bool use[N];
26 int link[N][M], cap[N], rank1[M][N];
27 bool dfs(int x)
28 {
29     for(int i = 1; i <= m; i++)
30         if(rank1[x][i] >= mi && rank1[x][i] <= mx && !use[i])
31         {
32             use[i] = true;
33             if(link[i][0] < cap[i])
34                 return link[i][++link[i][0]] = x, true;
35             else
36                 for(int j = 1; j <= cap[i]; j++)
37                 {
38                     if(dfs(link[i][j]))
39                         return link[i][j] = x, true;
40                 }
41         }
42     return false;
43 }
44 bool match(void)
45 {
46     memset(link, 0, sizeof(link));
47     for(int i = 1; i <= n; i++)
48     {
49         memset(use, 0, sizeof(use));
50         if(!dfs(i))
51             return false;
52     }
53     return true;
54 }
55 int main(void)
56 {
57     scanf("%d%d", &n, &m);
58     for(int i = 1; i <= n; i++)
59         for(int j = 1; j <= m; j++)
60         {
61             int x;
62             scanf("%d", &x);
63             rank1[i][x] = j;
64         }
65     for(int i = 1; i <= m; i++)
66         scanf("%d", cap + i);
67     int ans = m;
68     mx = mi = 1;
69     while(mi <= mx && mx <= m)
70     {
71         if(match())
72         {
73             ans = min(mx-mi+1, ans);
74             mi++;
75         }
76         else mx++;
77     }
78     printf("%d
", ans);
79     return 0;
80 }

网络流:110ms

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <climits>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <vector>
  8 #include <queue>
  9 #include <algorithm>
 10 #define esp 1e-6
 11 #define pb push_back
 12 #define in  freopen("in.txt", "r", stdin);
 13 #define out freopen("out.txt", "w", stdout);
 14 #define print(a) printf("%d
",(a));
 15 #define bug puts("********))))))");
 16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
 17 #define inf 0x3f3f3f3f
 18 using namespace std;
 19 typedef long long  LL;
 20 typedef vector<int> VI;
 21 typedef vector<int>:: iterator IT;
 22 #define N 3000
 23 #define M 50000
 24 
 25 struct EDGE
 26 {
 27     int i, c;
 28     EDGE *next, *ani;
 29 } *Edge[N], E[M << 1], BE[M << 1];
 30 int n, m, mx, mi, src, sink, cnt, ndot;
 31 int cap[N], rank1[M][N], vis[N], dfn[N], Now[N];
 32 
 33 void add(int i, int j, int c, EDGE &e1, EDGE &e2)
 34 {
 35     e1.i = j, e1.c = c, e1.next = Edge[i], e1.ani = &e2, Edge[i] = &e1;
 36     e2.i = i, e2.c = 0, e2.next = Edge[j], e2.ani = &e1, Edge[j] = &e2;
 37     BE[cnt] = E[cnt], BE[cnt + 1] = E[cnt + 1];
 38     cnt += 2;
 39 }
 40 void init(void)
 41 {
 42     cnt = 0;
 43     memset(Edge, 0, sizeof(Edge));
 44     src = 0, sink = 1;
 45     ndot = 2*n+2*m+2;
 46 }
 47 void update(void)
 48 {
 49     for(int i = 0; i < cnt; i++)
 50         E[i] = BE[i];
 51     for(int i = 1; i <= n; i++)
 52     {
 53         int u, v;
 54         for(EDGE *p = Edge[2*i^1]; p; p = p->next)
 55         {
 56             u = i, v = p->i/2 - n;
 57             if(rank1[u][v] >= mi && rank1[u][v] <= mx)
 58                 p->c = 1;
 59             else p->c = 0;
 60         }
 61     }
 62 }
 63 void bfs(void)
 64 {
 65     queue<int> q;
 66     q.push(sink);
 67     vis[sink] = 1;
 68     Now[0] = 1;
 69     while(!q.empty())
 70     {
 71         int u = q.front();
 72         int v;
 73         q.pop();
 74         for(EDGE *p = Edge[u]; p; p = p->next)
 75             if(!vis[v = p->i] && p->ani->c)
 76             {
 77                 vis[v] = 1;
 78                 dfn[v] = dfn[u] + 1;
 79                 Now[dfn[v]]++;
 80                 q.push(v);
 81             }
 82     }
 83 }
 84 int ISAP(int s, int end, int flow)
 85 {
 86     if(s == end)
 87         return flow;
 88     int i, tab = ndot -1, now = 0, vary;
 89     for(EDGE *p = Edge[s]; p && flow; p = p->next)
 90         if(p->c)
 91         {
 92             if(dfn[s] == dfn[i = p->i] + 1)
 93                 vary = ISAP(i, end, min(flow, p->c)),
 94                 p->c -= vary, p->ani->c += vary, now +=vary, flow -= vary;
 95             if(p->c)
 96                 tab =  min(tab, dfn[i]);
 97             if(dfn[src] == ndot)
 98                 return now;
 99         }
100     if(now == 0)
101     {
102         if(--Now[dfn[s]] == 0)
103             dfn[src] = ndot;
104         ++Now[dfn[s] = tab + 1];
105     }
106     return now;
107 }
108 int max_flow(int s, int end)
109 {
110     int ret = 0;
111     memset(Now, 0, sizeof(Now));
112     memset(dfn, 0, sizeof(dfn));
113 //    bfs();
114     Now[0] = ndot;
115     for(; dfn[s] < ndot;)
116         ret += ISAP(s, end, inf);
117     return ret;
118 }
119 int main(void)
120 {
121     
122     scanf("%d%d", &n, &m);
123     init();
124     for(int i = 1; i <= n; i++)
125     {
126         for(int j = 1; j <= m; j++)
127         {
128             int x;
129             scanf("%d", &x);
130             rank1[i][x] = j;
131             add(2*i^1, 2*(j+n), 1, E[cnt], E[cnt + 1]);
132         }
133         add(src, 2*i, inf, E[cnt], E[cnt + 1]);
134         add(2*i, 2*i^1, 1, E[cnt], E[cnt + 1]);
135     }
136     for(int i = 1; i <= m; i++)
137     {
138         scanf("%d", cap + i);
139         add(2*(i+n), 2*(i+n)^1, cap[i], E[cnt], E[cnt + 1]);
140         add(2*(i+n)^1, sink, inf, E[cnt], E[cnt + 1]);
141     }
142     int l = 1, r = m, mid;
143 //    mx =m, mi = 1;
144 
145     int ans = m;
146     while(l <= r)
147     {
148         mid = (l + r)>>1;
149         int flag = 0;
150         for(mi = 1, mx = mid; mx <= m; mx++, mi++)
151         {
152             update();
153             if(max_flow(src, sink) == n)
154             {
155                 int  temp = mid;
156                 ans = min(temp, ans);
157                 flag = 1;
158                 break;
159             }
160         }
161         if(flag)
162             r = mid-1;
163         else l = mid +1 ;
164 
165     }
166     printf("%d
", ans);
167     return 0;
168 }
原文地址:https://www.cnblogs.com/rootial/p/3313665.html