POI #Year2011 #Dinic #网络流 #贪心
容易想到拆点的费用流做法,但是二分再拆点的时间复杂度是不可接受的
考虑因为每个的时间 \(r\) 是定值,所以不可能出现做题个数差超过 \(1\) 的情况
所以每一轮每个分配一个,用 \(Dinic\) 在推进一次,知道满流
// Author: xiaruize
const int N = 1e6 + 10;
struct MF
{
struct edge
{
int v, nxt, cap, flow;
} e[N];
int fir[N], cnt = 0;
int n, S, T;
int maxflow = 0;
int dep[N], cur[N];
void init()
{
// cerr << "flag" << endl;
memset(fir, -1, sizeof(fir));
cnt = 0;
}
void addedge(int u, int v, int w)
{
e[cnt] = {v, fir[u], w, 0};
fir[u] = cnt++;
e[cnt] = {u, fir[v], 0, 0};
fir[v] = cnt++;
}
bool bfs()
{
queue<int> q;
memset(dep, 0, sizeof(int) * (n + 1));
dep[S] = 1;
q.push(S);
while (q.size())
{
int u = q.front();
q.pop();
for (int i = fir[u]; ~i; i = e[i].nxt)
{
int v = e[i].v;
if ((!dep[v]) && (e[i].cap > e[i].flow))
{
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[T];
}
int dfs(int u, int flow)
{
if ((u == T) || (!flow))
return flow;
int ret = 0;
for (int &i = cur[u]; ~i; i = e[i].nxt)
{
int v = e[i].v, d;
if ((dep[v] == dep[u] + 1) && (d = dfs(v, min(flow - ret, e[i].cap - e[i].flow))))
{
ret += d;
e[i].flow += d;
e[i ^ 1].flow -= d;
if (ret == flow)
return ret;
}
}
return ret;
}
void dinic()
{
while (bfs())
{
memcpy(cur, fir, sizeof(int) * (n + 1));
maxflow += dfs(S, INF);
// cerr << maxflow << endl;
}
}
} mf;
int n, m, r, t, k;
int cnt[N];
pii eg[N];
void solve()
{
mf.init();
mf.S = 0;
cin >> n >> m >> r >> t >> k;
mf.T = mf.n = n + m + 1;
rep(i, 1, k)
{
cin >> eg[i].first >> eg[i].second;
mf.addedge(eg[i].second, eg[i].first + m, INF);
}
rep(i, 1, m)
{
mf.addedge(0, i, 1);
}
int res = 0;
for (int i = 1; mf.maxflow < m && i * r <= t; i++)
{
int la = mf.maxflow;
rep(i, 1, n) mf.addedge(i + m, n + m + 1, 1);
mf.dinic();
res += (mf.maxflow - la) * i * r;
}
cout << mf.maxflow << ' ' << res << endl;
}
#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int testcase = 1;
// cin >> testcase;
while (testcase--)
solve();
#ifndef ONLINE_JUDGE
cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
return 0;
}
标签:mf,return,Contest,int,Programming,flow,ret,POI2011PRO,dep
From: https://www.cnblogs.com/xiaruize/p/18147875