Atcoder beginer contest 204 supplement record

Posted by edwardoka on Mon, 08 Nov 2021 20:04:50 +0100

Yes, vp I only wrote two questions in one game. I'm a colored pen

C - Tour

Given n points and m unidirectional edges, find out how many point pairs can satisfy (i,j) from i to j

Problem solving idea: when writing a topic, we think of using rings to write. We can calculate as long as we find the number of rings, but we can't find all rings. Because the given data range is very small (only 2000), the algorithm with time complexity of n ^ 2 can be accepted. Then we traverse the time when the whole graph is O (n), and N points are n ^ 2, Then we can write directly through violence

Reflection: considering the time complexity and not considering violent practices, the idea is too limited

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 10;
vector<vector<int> > G;
int vis[maxn];
int T,n,m;
int u,v;
ll ans = 0;
void BFS(int s)
{
	queue<int> q;
	q.push(s);
	vis[s] = 1;
	while(!q.empty())
	{
		int x = q.front();
		q.pop();
		for(int h:G[x])
		{
			if(vis[h] == 0)
			{
				vis[h] = 1;
				q.push(h);
			}
		}
	}
}
void DFS(int s)
{
	if(vis[s]) return;
	vis[s] = 1;
	for(auto h:G[s])
	{
		if(vis[h] == 0)
		{
			DFS(h);
		}
	}
	return;
}
void solve()
{
	scanf("%d %d",&n,&m);
	G.resize(maxn);
	for(int i = 1;i <= m;++i)
	{
		scanf("%d %d",&u,&v);
		G[u].emplace_back(v);
	}
	for(int i = 1;i <= n;++i)
	{
		for(int j = 1;j <= n;++j) vis[j] = 0;
		DFS(i);
		for(int j = 1;j <= n;++j)
		{
			if(vis[j]) ans++;
		}
	}
	printf("%lld\n",ans);
}
int main()
{
	T = 1;
	while(T--)
	{
		solve();
	}
	return 0;
}

D - Cooking 

Solution: given that n items need to be cooked, we have 2 pots. Please find the shortest time we need to cook

Problem solving idea: in the process of doing the problem, thinking about how to place the items has no impact on the final result. No matter what the final result is, only pot A and pot B add up to all the time. Then we assume that pot A has A large time, so for pot A, we should try to find the minimum value of A greater than half of all cooking time. But how to find it?

Idea 1: dichotomy, we can enumerate time through dichotomy, but how to linearly represent and modify the corresponding increasing and decreasing?

Therefore, the idea of dichotomy was rejected by us, but for any item at any time, if we need to put the item in, the time depends on the previous time. Analyzing the time complexity, we can find that the value of ai is not very large, so we can think that if there is an item that needs to store the previous i - 1 item, Then for the i-th time, we can calculate

Then, for pot A, set the dynamic programming transfer equation dp[i][j],i represents the ith item, and j represents the time that may be needed. For this moment, if we have something here, we can choose to put the item in pot b, then dp[i + 1][j] = 1; We can also choose to put things back into pot A, so dp[i + 1][j + a[i]] = 1

It should be noted that our boundary point is dp[0][0] = 1, and the boundary loop is from 0 - > n - 1

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
bool dp[110][maxn];
int T,n,m;
int a[110];
int sum = 0;
void solve()
{
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)
	{
		scanf("%d",&a[i]);
		sum += a[i];
	}
	dp[0][0] = 1;
	for(int i = 0;i < n;++i)
	{
		for(int j = 0;j <= sum;++j)
		{
			if(dp[i][j])
			{
				dp[i + 1][j] = 1;
				dp[i + 1][j + a[i + 1]] = 1;
			}
		}
	}
	for(int i = (sum + 1) / 2;i <= sum;++i)
	{
		if(dp[n][i])
		{
			printf("%d\n",i);
			break;
		}
	}
}
int main()
{
	solve();
	return 0;
}