ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 1154번 : 팀 편성
    알고리즘/백준(acmicpc.net) 문제풀이 2022. 1. 16. 19:55
    반응형

    https://www.acmicpc.net/problem/1154

     

    1154번: 팀 편성

    첫째 줄에 학생 수를 나타내는 자연수 N이 주어진다. (N≤1,000) 편의상 각 학생들은 1부터 N까지 번호가 붙어 있다고 가정한다. 둘째 줄부터 각 줄에 두 개의 자연수 a와 b가 빈 칸을 사이에 두고 주

    www.acmicpc.net

    학생들을 주어진 조건에 따라 두 그룹으로 나누는 문제이다.

    아이디어 : 

    어떤 학생과 친구가 아니라는 것은, 무조건 그 친구와 다른 그룹이어야 한다는 것이다.
    그렇다면, 답이 나오는 상황이라고 가정했을 때, 모든 학생에 대해서 해당 학생과 친구가 아닌 학생들을 전부 그룹으로 묶는 과정을 반복하면, 최종적으로는 두 그룹으로 나뉘어지게 될 것이다.
    그 두 그룹에 대해 검증을 한번 더 하면, 조건에 맞는 두 그룹으로 나눌 수 있다.

    구현 : 

    Union-Find 알고리즘을 사용했다.

    각 학생마다 친구가 아닌 학생들을 무조건 그룹으로 묶고, 이 과정을 전체 학생을 대상으로 반복한다.
    일반적인 상황이면 두 그룹으로 묶이겠지만, 모든 친구들이 서로 친구이면 그룹이 하나도 생기지 않게 된다.
    따라서 그룹으로 묶이지 않은 친구들은 그 친구들끼리 그룹으로 묶어준다.
    이렇게 나온 그룹의 개수가 1개 또는 2개여야 한다.

    다음으로 각 그룹에 대해 검증을 해보자. 그룹의 속한 임의의 학생 x는 그룹에 속한 다른 모든 학생들과 친구여야 한다.
    검증이 끝나면 정렬을 한번 해주고, 답을 출력한다.

    코드 : 

    #include <bits/stdc++.h>
    using namespace std;
    vector<int> G[1001];
    int arr[1001][1001];
    int p[1001];
    void init(){
    	for(int i=0; i<1001; ++i){
    		p[i]=i;
    	}
    }
    int find(int x){
    	if(x==p[x]) return x;
    	return p[x]=find(p[x]);
    }
    void unite(int a, int b){
    	int A=find(a);
    	int B=find(b);
    	if(A==1) p[B]=A;
    	else if(B==1) p[A]=B;
    	else p[A]=B;
    }
    int main(){
    	ios::sync_with_stdio(0); cin.tie(0);
    	int N; cin>>N;
    	init();
    	while(1){
    		int a,b; cin>>a>>b;
    		if(a==-1) break;
    		G[a].push_back(b);
    		G[b].push_back(a);
    		arr[a][b]=1;
    		arr[b][a]=1;
    	}
    	vector<int> v;
    	for(int i=1; i<=N; ++i){
    		v.clear();
    		for(int j=1; j<=N; ++j){
    			if(i==j) continue;
    			if(!arr[i][j]) v.push_back(j);
    		}
    		for(int j=1; j<v.size(); ++j){
    			unite(v[j-1], v[j]);
    		}
    	}
    	int visit[1001]={0, };
    	for(int i=1; i<=N; ++i){
    		visit[find(i)]++;
    	}
    	v.clear();
    	int cnt=0;
    	for(int i=1; i<=N; ++i){
    		if(visit[i]==1){
    			v.push_back(i);
    		}
    		else if(visit[i]>1){
    			cnt++;
    		}
    	}
    	if(!v.empty()) cnt++;
    	if(cnt>2){
    		cout << "-1\n";
    		return 0;
    	}
    	for(int i=1; i<v.size(); ++i){
    		unite(v[i-1],v[i]);
    	}
    	vector<int> res1;
    	vector<int> res2;
    	for(int i=1; i<=N; ++i){
    		if(find(i)==1) res1.push_back(i);
    		else res2.push_back(i);
    	}
    	for(int i=0; i<res1.size(); ++i){
    		for(int j=0; j<i; ++j){
    			if(!arr[res1[i]][res1[j]]){
    				cout << "-1\n";
    				return 0;
    			}
    		}
    	}
    	for(int i=0; i<res2.size(); ++i){
    		for(int j=0; j<i; ++j){
    			if(!arr[res2[i]][res2[j]]){
    				cout << "-1\n";
    				return 0;
    			}
    		}
    	}
    	cout << "1\n";
    	sort(res1.begin(), res1.end());
    	sort(res2.begin(), res2.end());
    	for(auto it:res1) cout << it << " ";
    	cout << "-1\n";
    	for(auto it:res2) cout << it << " ";
    	cout << "-1\n";
    }

     

    반응형

    '알고리즘 > 백준(acmicpc.net) 문제풀이' 카테고리의 다른 글

    1422번 : 숫자의 신  (0) 2022.01.22
    1369번 : 배열값  (0) 2022.01.22
    1131번 : 숫자  (0) 2022.01.14
    1125번 : 바닥 장식  (0) 2022.01.12
    18186번 : 라면 사기 (Large)  (0) 2022.01.09

    댓글

Designed by Tistory.