첫째, 분리 된 세트 것입니다
컴퓨터 과학, 일부 문제가있는 통합 및 거래에 대한 나무의 분리 된 세트 데이터 구조는 쿼리의 집합을 해체. 이 공동 - 검색 알고리즘 (노조 찾기 알고리즘) 데이터 구조에 대한 두 동작 시간을 정의는 :
- 찾기 : 속하는 요소를 결정하는 부분 집합. 이는 두 요소들이 동일한 서브 세트에 속하는 것인지를 결정하는데 사용될 수있다.
- 연합 : 두 집합 및 수집에.
둘째, 주요 작업
- 초기화 : 각 지점을 초기화 할 경우 자신의 컬렉션.
for(int i=1;i<=n;i++)
f[i]=i;
- 찾기 : 루트 노드입니다있는 요소 세트를 찾을 수 있습니다.
int find(int x)
{
while(f[x]!=x)
x=f[x];
return x;
}
- 병합 요소들의 두 세트를 하나 개의 집합으로 조합 여기서.
void Union(int x1,int x2)
{
int t1=find(x1);
int t2=find(x2);
if(t1!=t2)
f[t2]=t1;
}
셋째, 최적화
위의 코드는 간단하게 보이지만, 각 찾기 작업의 시간 복잡도는 우리가 나무에 특별한 치료를하지 않았기 때문에 O (H), H는 나무의 높이, 나무가 병합 트리에 계속 있도록 심각한 불균형을 일으킬 수있다, 최악의 경우 각 노드는 하나의 자식 노드를 가지고있다.
따라서 찾기 기능에 사용되는 경로를 압축 .
int find(int x) //查找x元素所在的集合,回溯时压缩路径
{
if (x != f[x])
{
f[x] = find(f[x]);
//从x结点搜索到祖先结点所经过的结点都指向该祖先结点
}
return f[x];
}
넷째, 템플릿 제목
#include<bits/stdc++.h>
using namespace std;
int n,m;
int f[10002];
int find(int x)
{
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
void Union(int x1,int x2)
{
int t1=find(x1);
int t2=find(x2);
if(t1!=t2) //祖先不一样
f[t2]=t1; //把t2的祖先变为x1的祖先t1
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=0;i<m;i++)
{
int z,x,y;
cin>>z>>x>>y;
if(z==1)
Union(x,y);
else
{
if(find(x)!=find(y))cout<<"N"<<endl;
else cout<<"Y"<<endl;
}
}
return 0;
}
다섯째, 최소 스패닝 트리
원본 이미지의 N 개의 꼭지점 연결된 그래프는 해당 노드의 모든 원 화상을 포함하는 최소 스패닝 트리 링크 서브 그래프이고,도를 유지하면서 최소의 통신이 존재한다.
최소 스패닝 트리 실제로 최소 무게 스패닝 트리라고합니다.
크루스 칼의 알고리즘
- 오름차순 중량에 따른 그래프는 모든 모서리
- 루프를 구성하는 경우, 정렬 된 모든 에지를 이송, 그 에지는 컬렉션에 추가
- 그것은 N-1면을 발견 할 때까지
#include<bits/stdc++.h>
using namespace std;
int n,m;
int s,maxm;
int p[100002];
struct node{
int u;
int v;
int c;
}info[100002];
bool cmp(node x1,node x2)
{
if(x1.c!=x2.c)return x1.c<x2.c;
else if(x1.u!=x2.u) return x1.u<x2.u;
else return x1.v<x2.v;
}
int find(int x) //查找x元素所在的集合,回溯时压缩路径
{
if (x!=p[x])
{
p[x]=find(p[x]);
}
return p[x];
}
void bcj(int x1,int x2)//把x2并入x1的集合
{
int t1,t2;//存储祖先节点
t1=find(x1);
t2=find(x2);
if(t1!=t2)p[t2]=t1;
}
int main()
{
cin>>n>>m;//n就是顶点数,m是边数
for(int i=1;i<=n;i++)
{
p[i]=i;
}
for(int i=0;i<m;i++)
{
cin>>info[i].u>>info[i].v>>info[i].c;
}
sort(info,info+m,cmp);
for(int i=0;i<m;i++)//遍历所有的边
{
if(find(info[i].u)!=find(info[i].v))
{
bcj(info[i].u,info[i].v);//把v并入u的集合
maxm=max(maxm,info[i].c);
}
}
cout<<n-1<<" "<<maxm;
return 0;
}