题目链接:
题目描述:
有n位顾客,f种食物,d种饮料。顾客都有自己喜欢的饮料和食物,每个顾客至少得到一种食物和一种饮料才会在餐厅就餐,否则立马走人。现在问最多能满足几位顾客?
解题思路:
0作为源点,[1, f] 为食物,0到 [1,f] 建边,边流量为每种食物的数目。[f+1, f+n] 代表顾客,[1, f] 与[f+1, f+n]建边,为了尽量满足更多的顾客,把每个顾客与其喜欢的食物之间的边流量赋为1。为了防止增广路时一个顾客选择多种食物和多种饮料的情况,应该对顾客进行拆点。[f+n+1, f+n+n]也代表顾客,[f+1, f+n] 与 [f+n+1, f+n+n] 之间连边,边流量为1。[f+n+n+1, f+n+n+d]代表饮料,f+n+n+d+1代表汇点,饮料与汇点连边,边的容量为每种饮料的数目。
这个题目时间卡的有一丢丢紧,扎扎用以前的dinic模板时候果断tle。天真的以为是用了邻接矩阵的原因,然后换成邻接表,还是t的哭瞎!!!!,最后多调试了几次后发现,我以前的dinic模板真的有问题。扎扎今天决定要更新一下dinic模板。
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 const int maxn = 810; 9 const int N = 900000; 10 const int INF = 0x3f3f3f3f; 11 struct Node 12 { 13 int to, next, flow; 14 } edge[N]; 15 int head[maxn], Layer[maxn], s, e, tot; 16 int vis[maxn]; 17 18 void Add (int from, int to, int flow) 19 { 20 edge[tot].to = to; 21 edge[tot].flow = flow; 22 edge[tot].next = head[from]; 23 head[from] = tot++; 24 } 25 26 bool CountLayer () 27 { 28 queue <int> Q; 29 memset (Layer, 0, sizeof(Layer)); 30 Q.push(s); 31 Layer[s] = 1; 32 33 while (!Q.empty()) 34 { 35 int u = Q.front(); 36 Q.pop(); 37 for (int i=head[u]; i!=-1; i=edge[i].next) 38 { 39 int v = edge[i].to; 40 if (!Layer[v] && edge[i].flow) 41 { 42 Layer[v] = Layer[u] + 1; 43 Q.push(v); 44 if (v == e) 45 return true; 46 } 47 } 48 } 49 50 return false; 51 } 52 53 int dfs (int start, int end, int maxflow) 54 { 55 if (start == end) 56 return maxflow; 57 58 int uflow = 0; 59 for (int i=head[start]; i!=-1; i=edge[i].next) 60 { 61 62 int v = edge[i].to; 63 if (Layer[v]==Layer[start]+1 && edge[i].flow) 64 { 65 int flow = min (maxflow-uflow, edge[i].flow); 66 flow = dfs (v, end, flow); 67 68 uflow += flow; 69 edge[i].flow -= flow; 70 edge[i^1].flow += flow; 71 72 if (maxflow == uflow) 73 break; 74 } 75 } 76 77 if (uflow == 0) 78 Layer[start] = 0; 79 return uflow; 80 } 81 int dinic ( ) 82 { 83 int maxflow = 0; 84 85 while (CountLayer ()) 86 maxflow += dfs (s, e, INF); 87 88 return maxflow; 89 } 90 int main () 91 { 92 char str[maxn]; 93 int n, f, d, v; 94 95 while (scanf ("%d %d %d", &n, &f, &d) != EOF) 96 { 97 memset (head, -1, sizeof(head)); 98 s = tot = 0; 99 e = f + n + n + d + 1; 100 101 for (int i=1; i<=f; i++) 102 { 103 scanf ("%d", &v); 104 Add (s, i, v); 105 Add (i, s, 0); 106 } 107 108 for (int i=f+n+n+1; i<e; i++) 109 { 110 scanf ("%d", &v); 111 Add (i, e, v); 112 Add (e, i, 0); 113 } 114 115 for (int i=1; i<=n; i++) 116 { 117 scanf ("%s", str+1); 118 for (int j=1; j<=f; j++) 119 if (str[j] == 'Y') 120 { 121 Add (j, f+i, 1); 122 Add (f+i, j, 0); 123 } 124 } 125 126 for (int i=1; i<=n; i++) 127 { 128 scanf ("%s", str+1); 129 for (int j=1; j<=d; j++) 130 if (str[j] == 'Y') 131 { 132 Add (f+n+i, f+n+n+j, 1); 133 Add (f+n+n+j, f+n+i, 0); 134 } 135 } 136 137 for (int i=f+1; i<=f+n; i++) 138 { 139 Add (i, i+n, 1); 140 Add (i+n, i, 0); 141 } 142 143 printf ("%d ", dinic()); 144 } 145 return 0; 146 }