خوارزمية كروسكال وبنية البيانات المنفصلة:هل أحتاج إلى السطرين التاليين من التعليمات البرمجية؟

StackOverflow https://stackoverflow.com/questions/5442275

سؤال

لقد قمت بتطبيق خوارزمية Kruskal في لغة C++ باستخدام بنية البيانات المنفصلة وفقًا لويكيبيديا مثل هذا:

#include <stdio.h>
#include <algorithm>
#define MAX_EDGES 10000000
#define MAX_VERTICES 200001
using namespace std;
int num_edges,num_vertices;
int total_cost=0;

struct edge{
    int v1,v2;
    int cost;
};

struct comp{
    bool operator()(const edge& e1,const edge& e2){
        return e1.cost<e2.cost;
    }
};

edge edges[MAX_EDGES];
int parent[MAX_VERTICES];
int rank[MAX_VERTICES];

int findset(int x){
    if(x!=parent[x]){
        parent[x]=findset(parent[x]);
    }
    return parent[x];
}

void merge(int x,int y){
    int px=findset(x),py=findset(y);
    if(rank[px]>rank[py]){
        parent[py]=px;
    }else{
        parent[px]=py;
    }
    if(rank[px]==rank[py]){
        ++rank[py];
    }
}

int main(){
    FILE* in=fopen("input","r");
    FILE* out=fopen("output","w");
    fscanf(in,"%d %d\n",&num_vertices,&num_edges);
    for(int i=1;i<=num_vertices;++i){
        parent[i]=i;
        rank[i]=0;
    }
    for(int i=0;i<num_edges;++i){
        fscanf(in,"%d %d %d\n",&edges[i].v1,&edges[i].v2,&edges[i].cost);
    }
    sort(edges,edges+num_edges,comp());
    for(int i=0;i<num_edges;++i){
        int s1=findset(edges[i].v1),s2=findset(edges[i].v2);
        if(s1!=s2){
            merge(s1,s2);
            total_cost+=edges[i].cost;
        }
    }
    fprintf(out,"%d\n",total_cost);
}

سؤالي هو:هل أحتاج إلى هذين السطرين من التعليمات البرمجية؟إذا كان الأمر كذلك، ما هي أهميتها؟

  1. int px=findset(x),py=findset(y);في الدمج بدلا من int px=parent[x],py=parent[y];
  2. parent[x]=findset(parent[x]); في findset بدلا من return findset(parent[x]);
هل كانت مفيدة؟

المحلول

1) findset(x) تُرجع الممثل القانوني للمجموعة التي يوجد بها x (جذر شجرة أسلافها).أنت بحاجة إلى ذلك لتتمكن من مقارنة ما إذا كان هناك عنصران في نفس المجموعة أم لا (لهما نفس الممثل)، parent[x] فقط تقوم بإرجاع أصل x في الشجرة، والذي قد لا يكون الجذر.

1 أ) لقد نسيت اختبار تطابق px و py merge.

2) إنه تحسين بحيث يتم إجراء المكالمات المستقبلية إليه findset سوف تعمل بشكل أسرع.لو parent[x] تستخدم للإشارة إلى أصلها الذي يشير إلى جذر شجرة مجموعتها بعد هذه الدعوة parent[x] سوف يشير مباشرة إلى الجذر.

نصائح أخرى

  1. أنت بحاجة إلى هذا لأنه x.parent ليس بالضرورة ممثل الفئة التي x ينتمي، وبالتالي فإن الخوارزمية لن تكون صحيحة بدونها.
  2. بدون المهمة، ستكون الخوارزمية دون المستوى الأمثل.هذا ال ضغط المسار التحسين، تمت مناقشته أيضًا في ويكيبيديا.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top