ADEGHK
A - Amanda Lounges
染色+dfs
分类 将
c
=
2
c=2
c=2的两边机场染色为
1
1
1,
c
=
0
c=0
c=0的两边机场染色为
−
1
-1
−1
对于上面两种情况,染色时如果出现矛盾情况,就直接“impossible”
c
=
1
c=1
c=1的两边机场建图连起来染色为0
这样就能把所有的机场分为两部分
一部分是color不为0的机场以及它相连的机场 另一部分是剩下的color全是0的机场
对两个部分进行dfs遍历染色 :
第一部分都是因为
c
=
1
c=1
c=1被连起来的,因此两边服务区情况应该不相同,一边是
−
1
-1
−1另一边一定是
1
1
1
第二部分全都是因为
c
=
1
c=1
c=1连接起来的,我们可以假设一个点是1或者-1,对剩下的所有点遍历两边,求出所需要建立服务区的最小值(因为要么建服务区,要么不建,是相对的,所以染色成-1和染色成1最终形成的-1和1的数量一定是相对的,知道一个就知道另一个情况的,所以直接取ab最小值即可)
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define xx first
#define yy second
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;
void ClearFloat()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
int v[N], n, m, x, t, T;
int e[N], ne[N], h[N], idx;
int color[N], flag, a, b, res;
bool st[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int dfs(int u, int c, int k)
{
if (k)
{
if (color[u] == 1)
b++;
else
a++;
}
else
{
if (color[u] == 1)
res++;
}
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (color[j] == c)
return 0;
if (!st[j])
{
st[j] = 1;
if (color[j] == 0)
color[j] -= c;
if (!dfs(j, color[j], k))
return 0;
}
}
return 1;
}
signed main()
{
ClearFloat();
memset(h, -1, sizeof h);
flag = 1;
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int a, b, c;
cin >> a >> b >> c;
if (c == 0)
{
if (color[a] == 1 || color[b] == 1)
flag = 0;
color[a] = color[b] = -1;
}
else if (c == 2)
{
if (color[a] == -1 || color[b] == -1)
flag = 0;
color[a] = color[b] = 1;
}
else
add(a, b), add(b, a);
}
// 操作c = 0和c = 2需要修建多少服务区并判断与c = 1相连的情况是否合法;
for (int i = 1; i <= n; i++)
{
if (!st[i] && color[i])
{
st[i] = 1;
if (!dfs(i, color[i], 0))
flag = 0;
}
}
// 给(c = 1 && st[i] == 0)的情况染色;
for (int i = 1; i <= n; i++)
{
if (st[i] == 1)
continue;
a = 0, b = 0, st[i] = 1, color[i] = 1;
if (dfs(i, 1, 1) == 0)
flag = 0;
res += min(a, b);
}
if (flag)
cout << res << endl;
else
cout << "impossible";
return 0;
}
D - Dice Game
直接求一下两个人的数字之和。因为求概率的时候都会约分掉
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define xx first
#define yy second
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;
void ClearFloat()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
int v[N], n, m, k, x, t, T;
signed main()
{
double sum1, sum2, a1, b1, a2, b2;
cin >> a1 >> b1 >> a2 >> b2;
sum1 = b1 + a1 + b2 + a2;
cin >> a1 >> b1 >> a2 >> b2;
sum2 = b1 + a1 + b2 + a2;
// cout << sum1 << " " << sum2 << endl;
if (sum1 == sum2)
cout << "Tie";
if (sum1 > sum2)
cout << "Gunnar";
if (sum2 > sum1)
cout << "Emma";
return 0;
}
E - Opening Ceremony
思维题 脑子转不过来的话可以写的麻烦一些
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, m, k, a[N];
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + n + 1);
int mi = 0;
for (int i = 1; i <= n; i++)
mi = min(mi + 1, a[i]);
cout << mi << "\n";
}
G - Outing
tarjan缩点+背包
不会tarjan缩点的可以看一下这篇文章讲的很详细
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define xx first
#define yy second
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;
void ClearFloat()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
int v[N], n, m, k, t, T;
vector<int> g[N];
int dfn[N], low[N], id[N], sz[N], cnt;
int stk[N], top, f[N], p[N];
bool in[N];
map<int, PII> mp;
void tarjan(int u)
{
dfn[u] = low[u] = ++k;
stk[++top] = u;
in[u] = 1;
for (auto j : g[u])
{
if (!dfn[j])
{
tarjan(j);
low[u] = min(low[u], low[j]);
}
else if (in[j])
low[u] = min(low[u], low[j]);
}
if (dfn[u] == low[u])
{
int y;
++cnt;
do
{
y = stk[top--];
in[y] = 0;
id[y] = cnt;
sz[cnt]++;
} while (y != u);
}
}
int find(int x)
{
if (x != p[x])
p[x] = find(p[x]);
return p[x];
}
signed main()
{
ClearFloat();
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> v[i];
g[i].push_back(v[i]);
}
for (int i = 1; i <= n; i++)
{
if (!dfn[i])
tarjan(i);
}
for (int i = 1; i <= n; i++)
p[i] = i;
for (int i = 1; i <= n; i++)
{
int x = id[i], y = id[v[i]];
if (find(x) != find(y))
p[find(x)] = p[find(y)];
}
for (int i = 1; i <= cnt; i++)
{
mp[find(i)].xx = max(mp[find(i)].xx, sz[i]);
mp[find(i)].yy += sz[i];
}
for (auto t : mp)
{
for (int i = m; i >= 0; i--)
{
for (int j = t.yy.xx; j <= t.yy.yy; j++)
if (i >= j)
f[i] = max(f[i], f[i - j] + j);
}
}
cout << f[m];
return 0;
}
H - Clock Pictures
KMP+倍增
谁能想到这是KMP啊
先sort以下 再把所有相邻的指针求一下间距,给其中一个倍增一倍,然后KMP找字串,能找到就可能是有相同时间
不会KMP的可以看一下这篇文章
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define xx first
#define yy second
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;
void ClearFloat()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
int v[N], f[N], n, m, k, x, t, T;
int nt[N];
void getnext()
{
int j, k;
j = 0, k = -1;
nt[0] = -1;
while (j < n)
{
if (k == -1 || f[j] == f[k])
{
j++, k++;
nt[j] = k;
}
else
k = nt[k];
}
}
bool kmp()
{
getnext();
int i = 0, j = 0;
while (i < 2 * n && j < n)
{
if (j == -1 || v[i] == f[j])
{
i++, j++;
}
else
j = nt[j];
}
if (j >= n)
return 1;
else
return 0;
}
signed main()
{
ClearFloat();
cin >> n;
for (int i = 1; i <= n; i++)
cin >> v[i];
for (int i = 1; i <= n; i++)
cin >> f[i];
sort(v + 1, v + 1 + n);
sort(f + 1, f + 1 + n);
v[0] = 360000 - v[n] + v[1], f[0] = 360000 - f[n] + f[1];
for (int i = 1; i < n; i++)
v[i] = v[i + 1] - v[i], f[i] = f[i + 1] - f[i];
for (int i = 0; i < n; i++)
v[i + n] = v[i];
if (kmp())
cout << "possible";
else
cout << "impossible";
return 0;
}
K - Train Passengers
模拟一下即可
#include <bits/stdc++.h>
using namespace std;
long long c;
int n;
int main()
{
long long num=0;
cin>>c>>n;
for(int i=1;i<=n;i++)
{
int le,in,wa;
cin>>le>>in>>wa;
if(i==1)
{
if(le!=0)
{
cout<<"impossible";
return 0;
}
}
if(i==n)
{
if(in!=0||wa!=0||num-le!=0)
{
cout<<"impossible";
return 0;
}
}
int sw=in-le;
if(num+sw>c||num+sw<0)
{
cout<<"impossible";
return 0;
}
else num+=sw;
if(num!=c&&wa!=0)
{
cout<<"impossible";
return 0;
}
}
cout<<"possible";
return 0;
}
∗
∗
下次一定
∗
∗
**下次一定**
∗∗下次一定∗∗