【最大流】bzoj1711: [Usaco2007 Open]Dining吃饭

正在网络流入门(原来这种题用网络流做)

Description

农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品并准备了D (1 <= D <= 100) 种饮料. 他的N ( 1 <= N <= 100)头牛都以决定了是否愿意吃某种食物和喝某种饮料. 农夫JOHN想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物和饮料. 每一件食物和饮料只能由一头牛来用. 例如如果食物2被一头牛吃掉了,没有别的牛能吃食物2.

Input

* 第一行: 三个数: N, F, 和 D

* 第2..N+1行: 每一行由两个数开始F_i 和D_i, 分别是第i 头牛可以吃的食品数和可以喝的饮料数.下F_i个整数是第i头牛可以吃的食品号,再下面的D_i个整数是第i头牛可以喝的饮料号码.

Output

* 第一行: 一个整数,最多可以喂饱的牛数.


题目分析

首先将源点连向所有食物;所有饮料连向汇点。接下来是中间奶牛的部分,容易发现如果简单地食物-奶牛-饮料一连,将会导致一头奶牛可能吃了很多饮料食物。这里有一种巧妙的处理方法:将一头奶牛拆成两个点,中间连一条容量为1的边,意味着一头牛只能占有一个食物/饮料。

话说这题在bzoj为什么会莫名其妙TLE啊……

 1 #include<bits/stdc++.h>
 2 const int maxn = 1035;
 3 const int maxm = 10035;
 4 const int INF = 2e9;
 5
 6 struct Edge
 7 {
 8     int u,v,f,c;
 9     Edge(int a=0, int b=0, int c=0, int d=0):u(a),v(b),f(c),c(d) {}
10 }edges[maxm];
11 int n,f,d,S,T,lv[maxn];
12 int edgeTot,head[maxn],nxt[maxm];
13
14 int read()
15 {
16     char ch = getchar();
17     int num = 0, fl = 1;
18     for (; !isdigit(ch); ch = getchar())
19         if (ch==‘-‘) fl = -1;
20     for (; isdigit(ch); ch = getchar())
21         num = (num<<1)+(num<<3)+ch-48;
22     return num*fl;
23 }
24 void addedge(int u, int v, int c)
25 {
26     edges[edgeTot] = Edge(u, v, 0, c), nxt[edgeTot] = head[u], head[u] = edgeTot++;
27     edges[edgeTot] = Edge(v, u, 0, 0), nxt[edgeTot] = head[v], head[v] = edgeTot++;
28 }
29 bool buildLevel()
30 {
31     memset(lv, 0, sizeof lv);
32     std::queue<int> q;
33     q.push(S), lv[S] = 1;
34     for (int tmp; q.size(); )
35     {
36         tmp = q.front(), q.pop();
37         for (int i=head[tmp]; i!=-1; i=nxt[i])
38         {
39             int v = edges[i].v;
40             if (!lv[v]&&edges[i].f < edges[i].c){
41                 lv[v] = lv[tmp]+1, q.push(v);
42                 if (v==T) return true;
43             }
44         }
45     }
46     return false;
47 }
48 int fndPath(int x, int lim)
49 {
50     if (x==T) return lim;
51     for (int i=head[x]; i!=-1; i=nxt[i])
52     {
53         int v = edges[i].v, val;
54         if (lv[x]+1==lv[v]&&edges[i].f < edges[i].c){
55             if ((val = fndPath(v, std::min(lim, edges[i].c-edges[i].f)))){
56                 edges[i].f += val, edges[i^1].f -= val;
57                 return val;
58             }else lv[v] = -1;
59         }
60     }
61     return 0;
62 }
63 int dinic()
64 {
65     int ret = 0, val;
66     while (buildLevel())
67         while ((val = fndPath(S, INF))) ret += val;
68     return ret;
69 }
70 int main()
71 {
72     memset(head, -1, sizeof head);
73     n = read(), f = read(), d = read();
74     S = 0, T = n*2+f+d+1;
75     for (int i=1; i<=n; i++)
76     {
77         int k1 = read(), k2 = read();
78         for (; k1; --k1)
79             addedge(read(), f+i, 1);
80         for (; k2; --k2)
81             addedge(f+i+n, read()+n*2+f, 1);
82         addedge(f+i, f+i+n, 1);
83     }
84     for (int i=1; i<=f; i++) addedge(S, i, 1);
85     for (int i=1; i<=d; i++) addedge(f+2*n+i, T, 1);
86     printf("%d\n",dinic());
87     return 0;
88 }

END

原文地址:https://www.cnblogs.com/antiquality/p/10351733.html

时间: 2024-07-29 23:13:12

【最大流】bzoj1711: [Usaco2007 Open]Dining吃饭的相关文章

Bzoj1711 [Usaco2007 Open]Dining吃饭

Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 872  Solved: 459 Description 农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品并准备了D (1 <= D <= 100) 种饮料. 他的N (1 <= N <= 10

BZOJ 1711: [Usaco2007 Open]Dining吃饭

1711: [Usaco2007 Open]Dining吃饭 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 902  Solved: 476[Submit][Status][Discuss] Description 农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品

BZOJ1711: [Usaco2007 Open]Dingin吃饭

1711: [Usaco2007 Open]Dingin吃饭 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 508  Solved: 259[Submit][Status] Description 农 夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品并准备了D (1

BZOJ 1711:[Usaco2007 Open]Dining吃饭(最大流)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1711 [题目大意] 每头牛都有一些喜欢的饮料和食物, 现在有一些食物和饮料,但是每样只有一份, 现在要求得到最多的牛使得都可以获得一份喜欢的饮料和一份喜欢的食物 [题解] 为了避免一份牛占用过多的资源,我们对牛进行拆点,增加边作为限制, 然后源点连接食物,汇点连接饮料,求最大流即可. [代码] #include <cstdio> #include <algorithm>

【最大流】【Dinic】bzoj1711 [Usaco2007 Open]Dingin吃饭

把牛拆点,互相连1的边. 把牛的食物向牛连边,把牛向牛的饮料连边. 把源点向牛的食物连边,把牛的饮料向汇点连边. 要把牛放在中间,否则会造成一头牛吃了自己的食物后又去喝别的牛的饮料的情况. #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define INF 2147483647 #define MAXN 411 #def

【BZOJ】1711: [Usaco2007 Open]Dining吃饭

[算法]最大流 [题解] S连向食物连向牛连向牛'连向饮料连向T. 经典的一个元素依赖于两个元素的建图方式. #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int maxn=100010,inf=0x3f3f3f3f; struct edge{int v,flow,from;}e[maxn]; int firs

bzoj 1711 [Usaco2007 Open]Dining吃饭&amp;&amp;poj 3281 Dining

最大流. 这东西好像叫三分图匹配. 源点向每个食物点连一条容量为1的边. 每个饮料点向汇点连一条容量为1的边. 将每个牛点拆点,食物点向喜欢它的牛的入点连一条容量为1的边,牛的出点向它喜欢的饮料点连一条容量为1的边. 最大流即为答案,每头牛拆点是为了保证每头牛只有一种食物和一种饮料. 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #inc

1711: [Usaco2007 Open]Dingin吃饭

1711: [Usaco2007 Open]Dingin吃饭 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 560  Solved: 290[Submit][Status][Discuss] Description 农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品

BZOJ 1711: [Usaco2007 Open]Dingin吃饭

Description 农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品并准备了D (1 <= D <= 100) 种饮料. 他的N (1 <= N <= 100)头牛都以决定了是否愿意吃某种食物和喝某种饮料. 农夫JOHN想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物