POI2011PRO-Programming Contest

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;
}
posted @ 2024-04-20 16:48  xiaruize  阅读(4)  评论(0)    收藏  举报