HDU 5923 및 검색 집합
8729 단어 데이터 구조
제목:
제목 은 이해 하기 어렵 습 니 다. 읽 은 후에 바로 하나의 집합 을 찾 습 니 다. 다른 블 로 그 는 지속 적 으로 사용 할 수 있 고 집합 을 찾 을 수 있 습 니 다. 저 는 보통 집합 을 사용 하고 AC 도 사용 할 수 있 습 니 다. 지속 적 이 고 집합 을 찾 을 수 없 기 때 문 입 니 다.그림 이 하나 있 고 나무 가 한 그루 있 습 니 다. 그리고 나무 에 있 는 모든 결점 은 그림 속 의 가장자리 에 있 는 정보 입 니 다. 그래서 그림 에 m 개의 가장자리 가 있 으 면 나무 에 m 개의 정점 이 있 습 니 다.그리고 q 번 의 질문 이 있 습 니 다. 매번 질문 할 때마다 몇 가지 점 을 주 고 나무 에서 이 점 을 찾 습 니 다. 그리고 그들의 모든 조상 들 도 이 집합 에 가입 한 다음 에 이 집합 을 그림 에 투사 하여 그림 의 연결 분량 을 구 합 니 다.정 답 은 분량 을 연결 하 는 개수 다.
문제 풀이:
4. 567917. 뿌리 결점 은 반드시 모든 조상 들 의 일원 이라는 것 을 발견 하기 어렵 지 않다. 우 리 는 DFS 를 한 번 만 한 다음 에 경 로 를 옮 겨 다 니 면 문의 의 집합 이다. 그리고 우 리 는 어떻게 연결 분량 을 구 하 는 지 고려 해 야 한다
4. 567917. 우 리 는 연결 분량 의 개 수 를 사용 하고 조사 할 수 있다. 왜냐하면 뿌리 노드 가 같 기 때문에 똑 같은 연결 분량 에 있 을 것 이다
4. 567917. 우 리 는 DFS 에서 하위 노드 에 부모 노드 의 계승 과 집합 을 찾 을 수 있 습 니 다. 그러면 Query 를 할 때 우 리 는 모든 노드 의 집합 을 고려 하고 조사 하면 됩 니 다. 그 다음 에 두 개의 for 순환, 첫 번 째 for 는 모든 query 를 스 캔 하고 두 번 째 for 스 캔 그림 의 모든 결점 을 스 캔 한 다음 에 다시 한 번 집합 을 찾 고 마지막 으로 하나의 for 로 한 번 스 캔 하면 됩 니 다.몇 개의 노드 만 있 으 면 몇 개의 연결 분량 이 있다
#include
#include
#include
#include
#include
#define debug(x) cout<
#define INF 0x3f3f3f3f
using namespace std;
const int maxv = 510;//
const int maxe = 10010;//
int n, m, t1, t2;
int head[maxe], cnt; // , head , , , MLE
int root[maxe][maxv];//
bool vis[maxv]; int Query, query[maxe], qcnt, ans; //
struct Edge {
int to, next;
} edge[maxe];
pair<int, int> pii;
vectorint , int> > vpii;
void init() {
memset(head, -1, sizeof head);
vpii.clear();
cnt = 0;
for (int i = 0; i <= m; i++)
for (int j = 0; j <= n; j++)
root[i][j] = j;// ,
}
void init_Query() {
memset(vis, false, sizeof vis);
ans = 0;
}
void addedge(int from, int to) {
edge[cnt].to = to;
edge[cnt].next = head[from];
head[from] = cnt++;
}
int Find(int tree_point, int graph_point) {//
if (root[tree_point][graph_point] == graph_point)
return graph_point;
return root[tree_point][graph_point] = Find(tree_point, root[tree_point][graph_point]);
}
void mix(int tree_point, int graph_point1, int graph_point2) {//
graph_point1 = Find(tree_point, graph_point1);
graph_point2 = Find(tree_point, graph_point2);
if (graph_point1 != graph_point2)
root[tree_point][graph_point2] = graph_point1;
}
void dfs(int u) {
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
memcpy(root[v], root[u], sizeof root[v]);
mix(v, vpii[v - 1].first, vpii[v - 1].second);
dfs(v);
}
}
int main(void) {
int T, kase = 1;
scanf("%d", &T);
while (T--) {
printf("Case #%d:
", kase++);
scanf("%d%d", &n, &m);
init();
addedge(0, 1);
for (int i = 2; i <= m; i++)
scanf("%d", &t1), addedge(t1, i); //
for (int i = 0; i < m; i++) //
scanf("%d%d", &t1, &t2), pii = make_pair(t1, t2), vpii.push_back(pii);
dfs(0);
scanf("%d", &Query);
while (Query--) {
init_Query();
scanf("%d", &qcnt);
for (int i = 0; i < qcnt; i++)
scanf("%d", &query[i]);
memcpy(root[m + 1], root[query[0]], sizeof root[m + 1]);// Query , ,
for (int i = 1; i < qcnt; i++)// query
for (int j = 1; j <= n; j++)//
mix(m + 1, Find(query[i], j), j);//
for (int i = 1; i <= n; i++)
if (!vis[Find(m + 1, i)])
vis[Find(m + 1, i)] = true, ans++;
cout << ans << endl;
}
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.