• 纳克萨玛斯「GDOI2007」(网络流)


    首先不考虑 (D) 的要求,可以想到一个网络流的建图模型:每个人当成一个点,每种角色也当成一个点,每个人能当某种角色就连一条容量是无穷大的边,每个人再限制只能流1的流量进来。但是这样跑不出答案,发现对于一种可行的流最后的答案是所有角色流量的最小值,那么我们可以考虑二分答案,建立一个汇点,将每种角色连向这个汇点一条容量为二分值的边,最后如果跑满了那么当前二分之一就是可行的。

    考虑 (D) 的要求,对于两个正营再各新建一个点,考虑源点连向这两个点的容量。假设两点的流量为 (x,y),那么 (x+y=m*now,|x-y|le DRightarrow x,yle frac{m*now+D}{2}),其中 (now) 是当前二分的答案。把容量设为 (frac{m*now+D}{2}) 即可。

    但是这样复杂度不优,无法通过此题。

    我们发现每个人跟他的名字(编号)无关,之和他能当什么角色有关,所以我们考虑将他们按角色这样分类,这样人数就从 (10^4) 降到了 (10^3) 级别了,可以通过此题。

    另外我还发现数据的漏洞,如果从 (n/m) 像下枚举答案会跑得更快

    using namespace std;
    const int MAXN = 200000;
    template <typename T>
    void read(T &x) {
    	T flag = 1;
    	char ch = getchar();
    	for (; '0' > ch || ch > '9'; ch = getchar()) if (ch == '-') flag = -1;
    	for (x = 0; '0' <= ch && ch <= '9'; ch = getchar()) x = x * 10+ ch - '0';
    	x *= flag;
    }
    struct node{
    	int pre, to, val;
    }edge[MAXN];
    int head[MAXN], tot = 1;
    int n, m, D, state[MAXN], S, T, v1, v2, num, cnt[2][1 << 11], id[2][1 << 11], d[MAXN], cur[MAXN];
    queue<int> q;
    bool bfs(int s, int t) {
    	for (int i = 0; i <= num; i++) d[i] = 0, cur[i] = head[i];
    	d[s] = 1;
    	q.push(s);
    	while (!q.empty()) {
    		int x = q.front();
    		q.pop();
    		for (int i = head[x]; i; i = edge[i].pre) {
    			int y = edge[i].to;
    			if (edge[i].val > 0 && !d[y]) d[y] = d[x] + 1, q.push(y);
    		}
    	}
    	return d[t] > 0;
    }
    int dinic(int x, int t, int flow) {
    	if (x == t || flow == 0) return flow;
    	int rest = flow;
    	for (int &i = cur[x]; i && rest > 0; i = edge[i].pre) {
    		int y = edge[i].to;
    		if (edge[i].val > 0 && d[y] == d[x] + 1) {
    			int k = dinic(y, t, min(rest, edge[i].val));
    			if (!k) d[y] = 0;
    			rest -= k; edge[i].val -= k; edge[i ^ 1].val += k;
    		}
    	}
    	return flow - rest;
    }
    int maxflow(int s, int t) {
    	int ret = 0, flow;
    	while (bfs(s, t))
    		while ((flow = dinic(s, t, 0x7f7f7f7f)) > 0)
    			ret += flow;
    	return ret;
    }
    void add_edge(int u, int v, int l) {
    	edge[++tot] = node{head[u], v, l}; head[u] = tot;
    	edge[++tot] = node{head[v], u, 0}; head[v] = tot;
    }
    void change_edge(int l) {
    	edge[++tot].val = l;
    	edge[++tot].val = 0;
    }
    int pos[12];
    void build(int ans) {
    	memset(head, 0, sizeof(head));
    	tot = 1;
    	add_edge(S, v1, (ans * m + D) >> 1);
    	add_edge(S, v2, (ans * m + D) >> 1);
    	for (int i = 1; i < (1 << m); i++) add_edge(v1, id[0][i], cnt[0][i]);
    	for (int i = 1; i < (1 << m); i++) add_edge(v2, id[1][i], cnt[1][i]);
    	for (int j = 0; j < m; j++)
    		for (int i = 1; i < (1 << m); i++)
    			if ((i >> j) & 1) add_edge(id[0][i], pos[j], 0x7f7f7f7f), add_edge(id[1][i], pos[j], 0x7f7f7f7f);
    	for (int j = 0; j < m; j++) add_edge(pos[j], T, ans);
    }
    void change(int ans) {
    	tot = 1;
    	change_edge((ans * m + D) >> 1);
    	change_edge((ans * m + D) >> 1);
    	for (int i = 1; i < (1 << m); i++) change_edge(cnt[0][i]);
    	for (int i = 1; i < (1 << m); i++) change_edge(cnt[1][i]);
    	for (int j = 0; j < m; j++)
    		for (int i = 1; i < (1 << m); i++)
    			if ((i >> j) & 1) change_edge(0x7f7f7f7f), change_edge(0x7f7f7f7f);
    	for (int j = 0; j < m; j++) change_edge(ans);
    }
    bool check(int ans) {
    	change(ans);
    	return maxflow(S, T) >= m * ans;
    }
    char s[15];
    int main() {
    	read(n); read(m); read(D);
    	S = 0;
    	v1 = ++num, v2 = ++num;
    	for (int i = 1; i <= n; i++) {
    		scanf("%s", s);
    		for (int j = 0; j < m; j++) state[i] |= (1 << j) * (s[j] - '0');
    		cnt[s[m] - '0'][state[i]]++;
    	}
    	for (int i = 1; i < (1 << m); i++) id[0][i] = ++num;
    	for (int i = 1; i < (1 << m); i++) id[1][i] = ++num;
    	for (int j = 0; j < m; j++) pos[j] = ++num;
    	T = ++num;
    	build(0);
    	for (int i = n / m; i; i--) {
    		if (check(i)) {
    			printf("%d
    ", i);
    			break;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    C# -- HttpWebRequest 和 HttpWebResponse 的使用
    C# -- Lambda 表达式的使用
    ASP.NET -- WebForm -- HttpRequest类的方法和属性
    ASP.NET -- WebForm -- HttpResponse 类的方法和属性
    C# -- 索引器、枚举类型
    C#设计模式之七桥接模式(Bridge Pattern)【结构型】
    C#设计模式之六适配器模式(Adapter Pattern)【结构型】
    C#设计模式之五原型模式(Prototype Pattern)【创建型】
    C#设计模式之四建造者模式(Builder Pattern)【创建型】
    C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/14349011.html
Copyright © 2020-2023  润新知