codeforces Round #677 (Div. 3) 1433D Districts Connection

这篇博客讨论了一道关于城市道路规划的题目,目标是在不引发帮派冲突的情况下连接所有地区。博主首先提出了自己的解决方案,即通过特定方式连接同帮派地区以避免直接连接。然后,博主分享了官方的简洁解法,即选取一帮派的地区作为中心,连接所有其他不同帮派的地区。博主从错误中学习,指出理解问题的重要性并提供了优化后的代码实现。
摘要由CSDN通过智能技术生成
题目链接

在这里插入图片描述

题目翻译:

小镇上有n个地区,第i个地区属于帮派ai。最开始所有地区之间都没有道路连接。
你是这个城市的市长,并想建立n-1条道路连接所有地区(两个地区可以被直接连接,也可以通过其它地区间接连接)。
如果两个属于同一帮派的地区被直接连接,则会起冲突。
你不想让这种事情发生,所以你的任务是建立n-1条道路,使得所有的地区都是可以相互抵达的(可能通过其他地区抵达)并且任意两个直接连接的地区属于不同的帮派。或者回答无法建立满足条件的n-1条道路。
你需要回答t个独立的测试用例。

我的解题思路:

可以先整理出所有属于同一帮派的地区,再以下图的方式连接所有地区。
在这里插入图片描述
先拿出一个1,把所有2都连接到这个1上,再把所有3都连接到同一个2上,以此类推,最后把剩下的1都连接到同一个4上就可以了。这样所有属于相同帮派的地区就不会相连接了。
另一个就是怎么判断结果是否存在。显然,当所有地区都属于同一帮派的时候,结果不存在。

我的代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
vector<int>v,vv[5010];
map<int,int>mm;
int main() {
//	freopen("1.txt","r",stdin);
	int t,n,a;
	cin>>t;
	while(t--) {
		cin>>n;
		v.clear();
		mm.clear();
		int num=1,maxlen=0,maxnum=0;
		for(int i=1; i<=n; i++) {
			cin>>a;
			if(mm[a]==0) {
				mm[a]=num;
				vv[num].clear();
				num++;
			}
			vv[mm[a]].push_back(i);
			if(vv[mm[a]].size()>maxlen) {
				maxlen=vv[mm[a]].size();
				maxnum=mm[a];
			}
		}
		if(maxlen==n){
			cout<<"NO"<<endl;
			continue;
		}
		cout<<"YES"<<endl;
		int start = vv[1][0];
		for(int i=2;i<num;i++){
			for(int j=0;j<vv[i].size();j++){
				cout<<start<<" "<<vv[i][j]<<endl;
			}
			start=vv[i][0];
		}
		for(int i=1;i<vv[1].size();i++){
			cout<<start<<" "<<vv[1][i]<<endl;
		}
	}
	return 0;
}

官方的解题思路:

看了答案,比我想的简单多了,随便找出一个任意帮派a的地区,将其他所有不属于帮派a的地区都连接到这个地区上,最后把帮派a剩余的地区连接到任意一个不属于帮派a的地区上。

代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 5050;
int a[N];
vector<int>v;
int main(){
//	freopen("1.txt","r",stdin);
	int t,n,flag,k;
	cin>>t;
	while(t--){
		cin>>n;
		v.clear();
		flag=0;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			if(a[i]!=a[1]) flag=1;
		}
		if(flag==0){
			cout<<"NO"<<endl;
			continue;
		}
		cout<<"YES"<<endl;
		for(int i=2;i<=n;i++){
			if(a[i]==a[1]) v.push_back(i);
			else{
				cout<<1<<" "<<i<<endl;
				k=i;
			}
		}
		for(int i=0;i<v.size();i++){
			cout<<k<<" "<<v[i]<<endl;
		}
	}
	return 0;
}

总结:

有思路之后还是应该再多想几分钟,换种思路可能花费的时间就会少很多很多。一开始理解错了,以为所有的地区应该连成一条直线,到最后了才反应过来…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值