ICPC 2019-2020 North-Western Russia Regional Contest train 补题记录

A.温暖的签到

 

E. Equidistant

题目大意:给定一颗n节点的树,给定几个点,问我们是否能够在树上找到一点到这几个点的距离是一样的

解题思路:我们把这几个点同时放进去并且进行BFS操作,并且我们开一个数组去记录有几个最终结点到这里的最短路径的的条数,因此对于每个经过的结点,我们若有dis[x] == dis[h] + 1,则cnt[x] += cnt[h],如果dis[x] > dis[h] + 1,则cnt[x] = cnt[h]

#include 
using namespace std;
const int maxn = 2e5 + 10;
const int inf = 0x3f3f3f3f;
vector G[maxn];
queue q;
int cnt[maxn];
int dis[maxn];
int n,m;
void BFS()
{
	while(!q.empty())
	{
		int x = q.front();
		q.pop();
		for(int f : G[x])
		{
			if(dis[f] == dis[x] + 1) cnt[f] += cnt[x];
			else if(dis[f] > dis[x] + 1)
			{
				dis[f] = dis[x] + 1;
				cnt[f] = cnt[x];
				q.push(f);
			}
		}
	}
}
void solve()
{
	scanf("%d %d",&n,&m);
	memset(dis,inf,sizeof dis);
	for(int i = 1;i <= n - 1;++i)
	{
		int u,v;
		scanf("%d %d",&u,&v);
		G[u].emplace_back(v);
		G[v].emplace_back(u);
	}
	int pos;
	for(int i = 1;i <= m;++i)
	{
		scanf("%d",&pos);
		dis[pos] = 0;
		cnt[pos] = 1;
		q.push(pos);
	}
	//cout << "??"<<"\n";
	BFS();
	for(int i = 1;i <= n;++i)
	{
		//cout<

I-Ideal Pyramid

题目大意:给定三维空间中的n个点,找出一个最小四棱锥能够将这些点全部包含在锥体里面,并且输出相应顶点的坐标

题目分析:由于这道题目求的是最小的高度,那么我们可以知道必定会存在一根柱子会与金字塔的面相切,那么对于金子塔上面的任意一个点(非顶点)(xi,yi,zi),和其顶点(x,y,z),对于x来说可以列出这样的式子h >=hi + \left | xi - x \right |,那么对于这个绝对值我们也可以进行一个拆分,让式子后面大于等于0,即可获得x的左右边界,同时用这种方法也可以获得y的左右边界,那么最后的点,我们可以知道是(xl + xr >> 1,yl + yr >> 1),对于高度来说,高度是需要取x和y之中长度相对来说比较长的那一根,因此我们也可以输出最后的结果了

#include 
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;

ll xr = - inf,xl = inf,yr = - inf,yl = inf;
ll x,y,h;
int n;
int main()
{
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)
	{
		scanf("%lld %lld %lld",&x,&y,&h);
		xr = max(h + x,xr);
		xl = min(x - h,xl);
		yr = max(h + y,yr);
		yl = min(y - h,yl);
	}
	printf("%lld %lld %lld\n",(xr + xl) >> 1,(yl + yr) >> 1,max((xr - xl + 1),(yr - yl + 1)) >> 1);
	return 0;
}

M-Managing Difficulties

题目大意:找到一个序列满足aj - ai = ak - aj

解题思路:先分析数据范围2000,那么n^2的时间复杂度是肯定可以被接受的,那么我们可以先把前面的 2 aj - ai给算出来,最后再去读入进来ak的时候将答案给计算进去(注意使用unordered_map,还有在使用count的时候时间复杂度会比直接查询要来的小)

#include 
using namespace std;
int T,n;
long long ans;
const int maxn = 2e3 + 10;
int a[maxn];
unordered_map mp;
int tmp;
void solve()
{
	scanf("%d",&n);
	ans = 0;
	mp.clear();
	for(int i = 1;i <= n;++i)
	{
		scanf("%d",&a[i]);
		if(mp.count(a[i]) != 0) ans += mp[a[i]];
		for(int j = 1;j < i;++j)
		{
			mp[2 * a[i] - a[j]]++;
		}
	}
	printf("%lld\n",ans);
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

J-Just the Last Digit

题目大意:给定一张图,aij代表从i到j的路有aij % 10条

解题思路:分析数据范围,数据范围比较小,那么我们可以直接通过枚举中间那个来判断相对应的路是否符合我们的要求

#include 
using namespace std;
const int maxn = 5e2 + 10;
int mp[maxn][maxn];
char str[maxn][maxn];
int ans[maxn][maxn];
int n;
void solve()
{
	scanf("%d",&n);
	//getchar();
	for(int i = 1;i <= n;++i)
	{
		scanf("%s",str[i] + 1);
	//	printf("%s\n",str[i] + 1);
	}
	for(int i = 1;i <= n;++i)
	{
		for(int j = 1;j <= n;++j)
		{
			//printf("str: %s",str[i]);
			mp[i][j] = str[i][j] - '0';
		}
	}
//	for(int i = 1;i <= n;++i)
//	{
//		for(int j = 1;j <= n;++j)
//		{
//			printf("%d ",mp[i][j]);
//		}
//		printf("\n");
//	}
	for(int k = 1;k <= n;++k)
	{
		for(int i = 1;i <= n - k;i++)
		{
			int f = i + k,cnt = 0;
			for(int j = i + 1;j < f;++j)
			{
				cnt = (cnt + ans[i][j] * mp[j][f]) % 10;
			}
			if(cnt != mp[i][f]) ans[i][f] = 1;
		}
	}
	for(int i = 1;i <= n;++i)
	{
		for(int j = 1;j <= n;++j)
		{
			printf("%d",ans[i][j]);
		} 
		printf("\n");
	}
}
int main()
{
	solve();
	return 0;
}

你可能感兴趣的:(训练小结,图论)