codeforces Round#677(Div。3)1433D地区接続

トピックリンク

ここに写真の説明を挿入

タイトルの翻訳:

ありN地区は中、そしてI-番目の地区はギャングに属している当初、すべての地域間に道路の接続はありませんでした。あなたはこの都市の市長であり、すべてのエリアを接続するためにn-1本の道路を建設したいと考えています(2つのエリアは直接接続することも、他のエリアを介して間接的に接続することもできます)。同じギャングに属する2つのエリアが直接接続されている場合、競合が発生します。これを望まないので、あなたの仕事は、すべてのエリアが互いに到達可能であり(おそらく他のエリアを介して)、2つの直接接続されたエリアが異なるギャングに属するようにn-1道路を構築することです。または、条件を満たすn-1本の道路を確立できないと答えます。t個の独立したテストケースに答える必要があります。



私の問題解決のアイデア:

次の図に示すように、最初に同じギャングに属するすべてのリージョンを分類してから、すべてのリージョンを接続できます。
ここに写真の説明を挿入
最初に1を取り出し、すべての2をこの1に接続し、次にすべての3を同じ2に接続し、以下同様に続き、最後に残りのすべての1を同じ4に接続します。このように、同じギャングに属するすべてのエリアが接続されるわけではありません。
もう1つは、結果が存在するかどうかを判断する方法です。明らかに、すべての地域が同じギャングに属している場合、結果は存在しません。

私のコード:
#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;
}

総括する:

アイデアが浮かんだら、もう数分考えてみてください。アイデアを変えるのにかかる時間が大幅に短縮される場合があります。最初はすべてのエリアを一直線につなぐべきだと誤解し、最後に気づきました…

おすすめ

転載: blog.csdn.net/lmmmmmmmmmmmmmmm/article/details/109221769