Codeforces Round #765 (Div. 2) A~C题解

Codeforces Round #765 (Div. 2) A~C题解

A. Not Shading

题意
每次操作可选择一个黑色格子将该行全染为黑色或该列染为黑色,求最少需要多少次操作使(r,c)位置为黑色,若无法得到输出-1。

做法

若(r,c)初始就是黑色,则操作0次
若r行或c列存在黑色格子,则操作1次
若存在黑色格子,则操作2次
若不存在黑色格子,则无解输出-1

#include<bits/stdc++.h>
using namespace std;
int n,m;
char a[109][109];
int main()
{
	int i,j,k,t,r,c;
	cin>>t;
	while(t--){
		int flag=0,flag1=0;
	scanf("%d%d%d%d",&n,&m,&r,&c);                        
	for(i=1;i<=n;i++)
	for(j=1;j<=m;j++)
	{
	cin>>a[i][j];
	if((i==r||j==c)&&a[i][j]=='B')flag=1;
	if(a[i][j]=='B')flag1=1;
	}
	if(a[r][c]=='B')printf("0\n");
	else if(flag)printf("1\n");
	else if(flag1)printf("2\n");
	else printf("-1\n");
	}
	return 0;
}

B. Not Sitting

题意

有n行m列座位,Tina选择k(0<=k<=nm-1)桶油漆进行染色,Rahul选择一个没有染色的座位后Tina选择一个座位,Tina想Rahul远一些,Rahul想离Tina近一些,他们每次的选择都是最明智的,求k等于0到nm-1时他们之间的距离

做法

由于Rahul想离Tina近一些,他最佳选择为中间的位置,当他选择四个顶点的位置时两人之间的距离一定最大,为n-1+m-1.所以用bfs从四个顶点向中心蔓延,记录每个点的距离,从小到大排序后输出

#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[500009],mv[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void bfs(int x,int y,int len){
	queue<pair<int,int> >p;
	pair<int,int> no,le;
	map<pair<int,int>,int>has;
	p.push({1,1});
	has[{1,1}]=len;
	p.push({1,y});
	has[{1,y}]=len;
	p.push({x,1});
	has[{x,1}]=len;
	p.push({x,y});
	has[{x,y}]=len;
	a[1]=len;
	a[y]=len;
	a[(x-1)*y+1]=len;
	a[x*y]=len;
	while(!p.empty()){
		no=p.front();
		p.pop();
		for(int i=0;i<4;i++){
			le.first=no.first+mv[i][0];
			le.second=no.second+mv[i][1];
			if(le.first>0&&le.first<=n&&le.second>0&&le.second<=m&&!has[le])
			{
				has[le]=has[no]-1;
				a[(le.first-1)*y+le.second]=has[le];
				p.push(le);
			}
		}
	}
	sort(a+1,a+x*y+1);
	for(int i=1;i<=x*y;i++)
	printf("%d ",a[i]);
	printf("\n");
}
int main()
{
	int i,j,k,t,r,c,x,y,z;
	cin>>t;
	while(t--){
	scanf("%d%d",&n,&m);                        
	bfs(n,m,n-1+m-1);
	}
	return 0;
}

C. Not Assigning

题意

给一颗大小为n的树,对所有边进行赋值,使每条边的权值为质数并且任意两条相邻边的权值之和也是质数

做法

由于除2以外任意两个质数的和都为偶数,所有要使任意两条相邻边的权值之和为质数,要有一边权值为2,并且每个点度数小于3(若某个点度数大于等于3,必然存在复数个权值为2或奇数的边).所以该树若满足条件必然为链状(每个点的度数小于等于2),使用dfs从链头遍历每条边按2和任意一个非2质数交替赋值,最后按输入顺序输出每条边的权值(输入时用map记录每条边的输入顺序)。

#include <bits/stdc++.h>
using namespace std;
int idx,e[200009],h[200009],ne[200009],r[200009],ans[200009],n;
map<pair<int,int>,int>has;
void add(int x,int y){
	e[idx]=y;
	ne[idx]=h[x];
	h[x]=idx++;
}
void dfs(int x,int flag,int val){
	for(int i=h[x];i!=-1;i=ne[i]){
		if(e[i]!=flag){	
		    ans[has[{x,e[i]}]]=val;
		    dfs(e[i],x,5-val);
		}
	}
}
int main()
{
    int t,i,j,m,k,x,y,star;
    cin>>t;
    while(t--){
    memset(r,0,sizeof r);
    memset(h,-1,sizeof h);
    scanf("%d",&n);
    for(i=1;i<=n-1;i++){
    	scanf("%d%d",&x,&y);
    	add(x,y);
    	add(y,x);
    	r[x]++;
    	r[y]++;
    	has[{x,y}]=i;
    	has[{y,x}]=i;
	}
	for(i=1;i<=n;i++)
	    if(r[i]>=3)break;
	if(i<=n){
		printf("-1\n");
		continue;
	}
	star=0;
	for(i=1;i<=n;i++)
	    if(r[i]==1){
	    	star=i;
	    	break;
	    }
	dfs(star,0,2);
	for(i=1;i<n;i++)
	printf("%d ",ans[i]);
	printf("\n");
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值