The 43 rd ACM Asia Nanjing Regional Contest
https://vj.ti12z.cn/b02428b1bbcf4609f7b121c06ef01b09?v=1564291265
A.
思路
当K为1时显然的和N的奇偶性有关,那么我们考虑一下K>1 K>1K>1的情况
对于先手的Adrien来说,他对任意的N颗石子,他都可以将这N颗石子分成两段相当数量的石子(从中间开始拿对于奇数拿一颗,对于偶数拿两颗),那么剩下的两段相当于是独立的两个相同的游戏了,如果后手拿其中一段,那么我先手就对另一段进行这样相同的拆分,那么能保证我先手总是有石子能拿,所以我先手必胜,也就是说当K>1 K>1K>1的时候先手必胜,K==1 K==1K==1的时候判断奇偶,N==0 N==0N==0的时候特判即可
#include <bits/stdc++.h> using namespace std; int n,k; int main() { while (~scanf("%d%d", &n, &k)) { if (n == 0) { printf("Austin\n"); return 0; } if (k == 1) { if (n % 2 == 0) { printf("Austin\n"); } else { printf("Adrien\n"); } } else { printf("Adrien\n"); } } }
G.
题解:
I
最大流。根据题目所给的数据,从勇士向怪物连边,流量上限均为 1。
源点连到每个勇士一条边,流量上限均为 1。源点连到另一个虚拟节点,流量上限为 k,该虚拟节点连向每个勇士,流量上限均为 1。
每个怪物连向汇点,流量上限均为 1。
求出最大流即为答案。
#include<bits/stdc++.h> using namespace std; int n,m,k; const int maxn=1e5+7; const int maxm=1e5+7; const int inf=0x3f3f3f3f; struct Dinic { struct Edge { int next, f, to; } e[maxm]; int head[maxn], dep[maxn], tol, ans; int cur[maxn]; int src, sink, n; void add(int u, int v, int f) { tol++; e[tol].to = v; e[tol].next = head[u]; e[tol].f = f; head[u] = tol; tol++; e[tol].to = u; e[tol].next = head[v]; e[tol].f = 0; head[v] = tol; } bool bfs() { queue<int> q; memset(dep, -1, sizeof(dep)); q.push(src); dep[src] = 0; while (!q.empty()) { int now = q.front(); q.pop(); for (int i = head[now]; i; i = e[i].next) { if (dep[e[i].to] == -1 && e[i].f) { dep[e[i].to] = dep[now] + 1; if (e[i].to == sink) return true; q.push(e[i].to); } } } return false; } int dfs(int x, int maxx) { if (x == sink) return maxx; for (int &i = cur[x]; i; i = e[i].next) { if (dep[e[i].to] == dep[x] + 1 && e[i].f > 0) { int flow = dfs(e[i].to, min(maxx, e[i].f)); if (flow) { e[i].f -= flow; e[i ^ 1].f += flow; return flow; } } } return 0; } int dinic(int s, int t) { ans = 0; this->src = s; this->sink = t; while (bfs()) { for (int i = 0; i <= n; i++) cur[i] = head[i]; while (int d = dfs(src, inf)) ans += d; } return ans; } void init(int n) { this->n = n; memset(head, 0, sizeof(head)); tol = 1; } } G; int main(){ scanf("%d%d%d",&n,&m,&k); G.init(n+m+2); for (int i=1;i<=n;i++){ int nn,x; scanf("%d",&nn); G.add(0,i,1); G.add(n+m+1,i,1); for (int j=1;j<=nn;j++){ scanf("%d",&x); G.add(i,x+n,1); } } for (int i=1;i<=m;i++){ G.add(i+n,n+m+2,1); } G.add(0,n+m+1,k); printf("%d\n",G.dinic(0,n+m+2)); }