연결되지 않은-설정하고 크루스 칼 최소 트리 알고리즘을 스패닝

첫째, 분리 된 세트 것입니다

컴퓨터 과학, 일부 문제가있는 통합 및 거래에 대한 나무의 분리 된 세트 데이터 구조는 쿼리의 집합을 해체. 공동 - 검색 알고리즘 (노조 찾기 알고리즘) 데이터 구조에 대한 두 동작 시간을 정의는 :

  • 찾기 : 속하는 요소를 결정하는 부분 집합. 이는 두 요소들이 동일한 서브 세트에 속하는 것인지를 결정하는데 사용될 수있다.
  • 연합 : 두 집합 및 수집에.

둘째, 주요 작업

  • 초기화 : 각 지점을 초기화 할 경우 자신의 컬렉션.
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];
}

넷째, 템플릿 제목

루오 구 P3367 [템플릿] 이산 집합

#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;
}

추천

출처www.cnblogs.com/jiyi-conding/p/11795008.html