您的位置:首页 > 其它

ZOJ 3642 Just Another Information Sharing Problem (最大流)

2015-10-09 02:57 435 查看
题意:

有若干个人,第i个人有ai条信息,他至少共享bi条,至多共享ci条,问里面的某个人他最多能获得多少消息

分析:

这个网络流的模型还是很明显的,S流到人,人再流到信息,信息再流到T这种模型唯一要注意的是,自己这个人本来就知道的信息不需要让别人来共享了

其实不用哈希来判断自己不需要被分享的,由于人→信息→汇,限制了流量为1的,不会算重的

直接S→x,INF流量,最大流就是获得的信息数了

代码:

//
//  Created by TaoSama on 2015-10-08
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 4e2 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int M = 1e5 + 10;

int head
, pnt[M], cap[M], nxt[M], cnt;
void add_edge(int u, int v, int w) {
pnt[cnt] = v;
cap[cnt] = w;
nxt[cnt] = head[u];
head[u] = cnt++;
}

void add_double(int u, int v, int w1, int w2 = 0) {
add_edge(u, v, w1);
add_edge(v, u, w2);
}

int lev
, cur
;
bool bfs(int s, int t) {
queue<int> q;
memset(lev, 0, sizeof lev);
q.push(s); lev[s] = 1;
while(q.size() && !lev[t]) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = nxt[i]) {
int v = pnt[i];
if(cap[i] > 0 && !lev[v]) {
lev[v] = lev[u] + 1;
q.push(v);
}
}
}
return lev[t];
}

int dfs(int u, int t, int delta) {
if(u == t || !delta) return delta;
int ret = 0;
for(int i = cur[u]; ~i; i = nxt[i]) {
int v = pnt[i];
if(cap[i] > 0 && lev[v] == lev[u] + 1) {
int d = dfs(v, t, min(cap[i], delta));
cur[u] = i;
ret += d; delta -= d;
cap[i] -= d; cap[i ^ 1] += d;
if(delta == 0) return ret;
}
}
lev[u] = 0;
return ret;
}

int dinic(int s, int t) {
int ret = 0;
while(bfs(s, t)) {
for(int i = s; i <= t; ++i) cur[i] = head[i];
ret += dfs(s, t, INF);
}
return ret;
}

int n;

int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);

while(scanf("%d", &n) == 1) {
cnt = 0; memset(head, -1, sizeof head);
int s = 0, sz = 0;
map<int, int> mp;
for(int i = 1; i <= n; ++i) {
int a, b, c; scanf("%d%d%d", &a, &b, &c);
add_double(s, i, c);
while(a--) {
int x; scanf("%d", &x);
if(mp.count(x)) x = mp[x];
else x = mp[x] = ++sz;
add_double(i, n + x, 1);
}
}
int t = n + sz + 1;
for(int i = 1; i <= sz; ++i) add_double(n + i, t, 1);
int x; scanf("%d", &x);
add_double(s, x, INF);
printf("%d\n", dinic(s, t));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  最大流