AtCoder Beginner Contest 226
AtCoder Beginner Contest 226
C - Martial artist
题意:一共有n个功夫,学习一个功夫都需要花费一定的时间,学习第某一个功夫之前都要学习指定的功夫,问学习完第n个功夫至少花费多少时间。
思路:因为想要学会第n个功夫就必须要学习其指定的功夫,可以用dfs来解决,dfs(x)动作代表队含义是学习完第x的功夫需要用多少时间,对于我们已经搜索过的,就标记下,不用多次搜索。
代码:
#include <bits/stdc++.h>
#define pb push_back
#define LL long long
using namespace std;
const int N = 200010;
int n;
int t[N];
vector<int> a[N];
LL ans;
bool vis[N];
void dfs(int x)
{
vis[x] = true;
for(auto it : a[x])
{
if(!vis[it])
{
ans += t[it];
vis[it] = true;
dfs(it);
}
}
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++ )
{
cin >> t[i];
int k;
cin >> k;
for(int j = 1;j <= k; j ++ )
{
int x;
cin >> x;
a[i].pb(x);
}
}
dfs(n);
cout << ans + t[n] << endl;
// system("pause");
return 0;
}
D - Teleportation
题意:给你n个点的坐标,你可以定义一个二元组<a, b>,通过它你能从(x, y)传送到(x + a, y + b),可以操作无数次。问你至少需要定义多少二元组,你可以从中选择任意一个二元组任意一次操作,使得你可以任意一个点能到达其他任意一个点。
思路:对于每两个坐标做差并同时除以gcd存到一个集合里面,然后对集合去重,答案就是集合的大小。
#include <bits/stdc++.h>
using namespace std;
int n;
vector<pair<int,int>>p,q;
int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; i ++ )
{
int x, y;
scanf("%d %d",&x,&y);
p.push_back({x,y});
}
for(int i = 0; i < n; i ++ )
{
for(int j = 0; j < n; j ++ )
{
if(i != j)
q.push_back({p[i].first - p[j].first,p[i].second - p[j].second});
}
}
for(int i = 0; i < q.size(); i ++)
{
if(q[i].first == 0){
if(q[i].second > 0) q[i].second = 1;
else q[i].second = -1;
}
else if(q[i].second == 0){
if(q[i].first > 0) q[i].first = 1;
else q[i].first = -1;
}else{
int x = abs(__gcd(q[i].first, q[i].second));
q[i].first /= x, q[i].second /= x;
}
}
sort(q.begin(),q.end());
q.erase(unique(q.begin(), q.end()),q.end());
printf("%d\n",q.size());
return 0;
}
E - Just one
题意:给你N个顶点和M条无向边,你可以随意定义边的方向,使得每一个顶点都只能有一条到达其他顶点的边,问你规划该图的方案数。
思路:本题的结论是对于每一个连通块,如果存在边的数目不等于顶点的数目,答案就是0。否则,答案就是\(2^n\),n为连通块的数目。
代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef long long LL;
const int N = 200010;
int n, m;
vector<pair<int,int>>edges;
int cnt1[N], cnt2[N];//分别记录每个联通块点的数目和边的数目
int p[N];
int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
scanf("%d %d",&n, &m);
for(int i = 1; i <= m; i ++ )
{
int x, y;
scanf("%d %d",&x, &y);
edges.pb({x, y});
}
for(int i = 1; i <= n; i ++ ) p[i] = i;
for(int i = 0; i < m; i ++ )
{
int fa = find(edges[i].fi);
int fb = find(edges[i].se);
if(fa != fb) p[fa] = fb;
}
vector<int>q;//记录连通块
for(int i = 1; i <= n; i ++ )
{
int now = find(i);
if(!cnt1[now]) q.pb(now);
cnt1[now] ++;
}
for(int i = 0; i < m; i ++ )
{
int now = find(edges[i].fi);
cnt2[now] ++;
}
bool flag = false;
for(auto it : q){
if(cnt1[it] != cnt2[it]){
flag = true;
break;
}
}
if(flag){
puts("0");
return 0;
}
LL ans = 1;
for(int i = 1; i <= q.size(); i ++ ) ans = (ans * 1LL * 2) % 998244353;
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号