Gym - 101845F 最大流

The UN finals are here!, the coaches/ex-coaches team is creating a new exciting contest to select which teams will compete in the Colombian finals. Ivan said: the rules are clear, the only limitation to enroll teams in the Colombian finals is to pick a maximum of k teams per career. A team can be labeled with career X if there is no career Y such that more team members are enrolled in career Y than in career X. Finally, each team consists of three students (as usual).

Someone in the UN campus (UN finals are pretty popular) said, hey you guys should pick the teams careers in such a way that it maximizes the number of enrolled teams. Diego said: ah that is too easy. You will prove Diego right (or wrong). Given the description of the teams, output the maximum number of teams that can be enrolled in the Colombian finals.

Input

The first line is n (1?≤?n?≤?100) - the number of teams that registered to participate in the UN finals.

Next n lines contains each the
information from each team, that is, there will be three strings per
team (one per team member) separated by a single space. Each string
consists of distinct upper case letters which represent the careers that
a team member is studying (UN students love to study multiple careers).

The last line contains an integer k (1?≤?k?≤?n) - the maximum allowed number of teams per career.

Output

Print a single integer - the maximum number of teams that can be enrolled.

Example

Input

5A ABC BC C CB B BA A AC AC CB2

Output

5

Note

In the first example first and fourth team can represent career A, second and fifth team can represent career C and third can represent team B.

吐槽一点:数据真水,我模拟都过了。。

应该是网络流的裸题;

至于匹配问题的话,匈牙利也可以;

不过网络流建边也比较容易;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 200005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-4
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;
inline ll rd() {
	ll x = 0;
	char c = getchar();
	bool f = false;
	while (!isdigit(c)) {
		if (c == ‘-‘) f = true;
		c = getchar();
	}
	while (isdigit(c)) {
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	return f ? -x : x;
}

ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; }

/*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
	if (!b) {
		x = 1; y = 0; return a;
	}
	ans = exgcd(b, a%b, x, y);
	ll t = x; x = y; y = t - a / b * y;
	return ans;
}
*/

int n;
int k;

string s[104][3];
map<char, int>mp;
int fg[103][30];
int vis[2000];
int str[1003];
int car[103];
int st, ed;
struct node {
	int u, v, nxt, w;
}edge[maxn << 1];

int head[maxn], cnt;

void addedge(int u, int v, int w) {
	edge[cnt].u = u; edge[cnt].v = v; edge[cnt].nxt = head[u];
	edge[cnt].w = w; head[u] = cnt++;
}

int rk[maxn];

int bfs() {
	queue<int>q;
	ms(rk);
	rk[st] = 1;
	q.push(st);
	while (!q.empty()) {
		int tmp = q.front(); q.pop();
		for (int i = head[tmp]; i != -1; i = edge[i].nxt) {
			int to = edge[i].v;
			if (rk[to] || edge[i].w <= 0)continue;
			rk[to] = rk[tmp] + 1; q.push(to);
		}
	}
	return rk[ed];
}

int dfs(int u, int flow) {
	if (u == ed)return flow;
	int add = 0;
	for (int i = head[u]; i != -1 && add < flow; i = edge[i].nxt) {
		int v = edge[i].v;
		if (rk[v] != rk[u] + 1 || !edge[i].w)continue;
		int tmpadd = dfs(v, min(edge[i].w, flow - add));
		if (!tmpadd) { rk[v] = -1; continue; }
		edge[i].w -= tmpadd; edge[i ^ 1].w += tmpadd;
		add += tmpadd;
	}
	return add;
}

int ans;
void dinic() {
	while (bfs())ans += dfs(st, inf);
}

int main() {
	//   ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n; memset(head, -1, sizeof(head));
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= 3; j++)cin >> s[i][j];
	}
	cin >> k;
	for (int i = 1; i <= n; i++) {
		mp.clear();
		for (int j = 1; j <= 3; j++) {
			for (int y = 0; y < s[i][j].length(); y++) {
				mp[s[i][j][y]]++;
			}
		}
		int maxx = -1;
		for (char ch = ‘A‘; ch <= ‘Z‘; ch++) {
			maxx = max(maxx, mp[ch]);
		}
		for (char ch = ‘A‘; ch <= ‘Z‘; ch++) {
			if (mp[ch] == maxx) {
				fg[i][ch - ‘A‘ + 1] = 1;
			}
		}
	}
	st = 0; ed = 1000;
	for (int i = 1; i <= n; i++)addedge(st, i, 1), addedge(i, st, 0);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= 26; j++) {
			if (fg[i][j]) {
				addedge(i, j + n + 1, 1); addedge(j + 1 + n, i, 0);
			}
		}
	}
	for (int i = 1; i <= 26; i++)addedge(i + n + 1, ed, k), addedge(ed, i + 1 + n, 0);
	dinic();
	cout << ans << endl;
	return 0;
}

原文地址:https://www.cnblogs.com/zxyqzy/p/10300762.html

时间: 2024-10-23 16:54:08

Gym - 101845F 最大流的相关文章

Codeforces Gym 100203I I WIN 最大流

原题链接:http://codeforces.com/gym/100203/attachments/download/1702/statements.pdf 题解 首先寻找每个I,然后枚举形状,如果匹配的话,就将源点连一条边到当前匹配的W,再从W连条边到I,I需要拆点,然后将拆点后面的那个点连接到N,从N连接到汇点.所有边的容量都是1.需要注意避免产生重边.然后最大流就是答案. 代码 #include<iostream> #include<stack> #include<ve

Codeforces Gym 100002 E &quot;Evacuation Plan&quot; 费用流

"Evacuation Plan" Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100002 Description The City has a number of municipal buildings and a number of fallout shelters that were build specially to hide municipal workers in case 

Codeforces Gym 101190M Mole Tunnels - 费用流

题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\right\rfloor$个巢穴连通.第$i$个巢穴在最终时允许$c_i$只醒来的鼹鼠最终停留在这.已知第$i$只鼹鼠在第$p_i$个巢穴睡觉.要求求出对于每个满足$1 \leqslant k \leqslant n$的$k$,如果前$k$只鼹鼠醒来,最小的移动距离的总和. 考虑费用流的建图和暴力做法,把原图的

Gym - 102346G Getting Confidence 最小费用最大流

Gym - 102346GGetting Confidence 题意:n*n的格子,每个格子上有一个数,要求每行每列都只能拿一个数,使得乘积最大,然后输出每列选择的是第几行的数. 如果是加法的话,那么很明显,就是一个网络流.可是,现在是乘法怎么办,很简单,直接取log,那么乘法便转换成了加法,然后就可以建图. 每行每列只能取一个数,就相当于行列是拆开的点,因为需要输出的是列的信息,那么源点向每一列建一条流量为1,费用为0的边,而每一行向汇点建一条流量为1,费用为0的边. 再对于每个格子,每一列向

codeforces gym 100357 I (费用流)

题目大意 给出一个或与表达式,每个正变量和反变量最多出现一次,询问是否存在一种方案使得每个或式中有且仅有一个变量的值为1. 解题分析 将每个变量拆成三个点x,y,z. y表示对应的正变量,z表示对应的反变量. 由S向每个点的x部连一条流量为1的边,表示该变量的某个正变量或反变量的取值为1. 由每个点的x部向y部和z部分别连一条流量为1的边,表示每个正变量和反变量仅有一个取值为1. 若某个或式中含有某个变量,则由该变量的y部或z部向或式连一条流量为1的边.表示该变量可以使该或式的结果为1. 由每个

Codeforces Gym 101190 NEERC 16 .D Delight for a Cat (上下界的费用流)

ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜 ,因此一个小时内他只能选择睡觉或者打隔膜,当然他也必须选择睡觉或打隔膜,对于每一个小时,他选择睡觉或 打隔膜的愉悦值是不同的,对于第i个小时,睡觉的愉悦值为si,打隔膜的愉悦值为ei,同时又有一个奥妙重重的 规定:对于任意一段连续的k小时,ls必须至少有t1时间在睡觉,t2时间在打隔膜.那么ls想让他获得的愉悦值尽 量大,他该如何选择呢? 题意:就是N天,每天可以选择S或者E,每一天S或者E有

Gym - 101908G Gasoline 二分+最大流

After the end of the truck drivers' strike, you and the rest of Nlogônia logistics specialists now have the task of planning the refueling of the gas stations in the city. For this, we collected information on stocks of RR refineries and about the de

Gym - 101908G 二分答案+最大流

After the end of the truck drivers' strike, you and the rest of Nlog?nia logistics specialists now have the task of planning the refueling of the gas stations in the city. For this, we collected information on stocks of R refineries and about the dem

Gym 101917 E 简单计算几何,I 最大流

题目链接 https://codeforces.com/gym/101917 E 题意:给定一个多边形(n个点),然后逆时针旋转A度,然后对多边形进行规约,每个点的x规约到[0,w]范围内,y规约到[0,h]范围内,输出规约后的结果. 解析:求出来 多边形的长和宽,再和w,h比较,对点按比例进行缩放就好了. (多边形旋转其实是绕给出的第一个点旋转,以为是绕原点wa了1发). AC代码 1 #include <bits/stdc++.h> 2 #define Vector Point 3 usi