📌 주요 조건
- 회문: 앞 뒤 방향으로 볼 때 같은 순서의 문자로 구성된 문자열 ex) abba, kayak
- 유사회문: 그 자체는 회문이 아니지만 한 문자를 삭제하여 회문으로 만들 수 있는 문자열 ex) summuus
- 출력 값
- 회문일 경우 0
- 유사회문일 경우 1
- 그 외는 2
👉 투 포인터 활용
#include <iostream>
#include <vector>
using namespace std;
int checkStr(string str, int i, int j, bool chance) {
while (i < j) {
if (str[i] == str[j]) {
i++;
j--;
continue;
}
// 그 자체로 회문은 아닌 경우 + 한 문자 삭제할 수 있는 기회 있는 경우
if (chance) {
// 유사회문인 경우
if (checkStr(str, i+1, j, false) == 0 || checkStr(str, i, j-1, false) == 0) {
return 1;
}
// 회문도 유사회문도 아닌경우
return 2;
}
// 그 자체로 회문은 아닌 경우 + 한 문자 삭제할 수 있는 기회 없는 경우
// 회문도 유사회문도 아닌 경우
return 2;
}
// 회문인 경우
return 0;
}
int main() {
int T;
scanf("%d", &T);
for (int i=0; i<T; i++) {
char ch[100001];
scanf("%s", ch);
string str = ch;
int endIdx = str.size()-1;
printf("%d\n", checkStr(str, 0, endIdx, true));
}
return 0;
}
📌 주요 조건
i) 유지비의 합을 최소로 만들 것
ii) 마을을 두 개의 분리된 마을로 분할할 것
i) Minimum Spanning Tree 를 구한 후
ii) 해당 MST에서 가장 가중치가 큰 길을 하나 제거하여 두 개의 마을로 분리
📌 입력 조건
2 <= 집의 개수 <= 100,000
1 <= 길의 개수 <= 1,000,000
Kruskal vs Prim ❓
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Road { // edge
int houseA; // node1
int houseB; // node2
int cost; // edge의 가중치
};
vector<int> parents(100001);
bool cmp(const Road &a, const Road &b) {
return a.cost < b.cost;
}
int getParent(int house) {
if (parents[house] == house) {
return house;
}
return parents[house] = getParent(parents[house]); // path compression
}
void unionHouses(int houseA, int houseB) {
int a = getParent(houseA);
int b = getParent(houseB);
if (a < b) { parents[b] = a; }
else { parents[a] = b; }
}
int main() {
// 집의 개수 N, 길의 개수 M
int N, M;
scanf("%d %d", &N, &M);
// A번 집과 B번 집을 연결하는 길의 유지비가 C
int A, B, C;
vector<Road> roads;
for (int i=0; i<M; i++) {
scanf("%d %d %d", &A, &B, &C);
roads.push_back({A, B, C});
}
// Kruskal's Algorithm 활용
// Road(edge)의 가중치를 기준으로 오름차순 정렬
sort(roads.begin(), roads.end(), cmp);
// House(node)의 parents 정보 초기화
// 처음에는 각자 자기 자신이 parents
for (int i=1; i<=N; i++) {
parents[i] = i;
}
vector<int> selectedRoads;
for (int i=0; i<M; i++) {
// parent가 다르다는 것은 아직 두 House 사이에 경로가 없다는 뜻 (사이클 X)
if (getParent(roads[i].houseA) != getParent(roads[i].houseB)) {
// parent를 같게 만들어 하나의 그래프로 합치기
unionHouses(roads[i].houseA, roads[i].houseB);
// Road의 가중치 저장
selectedRoads.push_back(roads[i].cost);
}
}
// 마을 분할
// 선택된 Road의 가중치 중 가장 큰 가중치를 갖는 Road는 제외하고 가중치 합 구하기
int count = selectedRoads.size() - 1;
int answer = 0;
for (int i=0; i<count; i++) {
answer += selectedRoads[i];
}
// 없애고 남은 길 유지비의 합의 최솟값을 출력
printf("%d", answer);
return 0;
}