先简单说一下,生成最小树一般常用两种算法,一种是prim另一种是kruskal,两种算法也各有利弊,比如说prim编程比较复杂一些而kruskal编程则相对容易一些,但是时间复杂度却差了些。
prim跟dijkstra差不多,简单来说prim适合稠密图,而kurskal则适合稀疏图。

1.POJ - 1251(生成最小树模板题)

这个题也就是把字母转换成数字,直接套用模板即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 1010
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v,w;
}edge[maxn];
int f[maxn];
int ans=0,k=0;
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}

void kruskal(){
    ans=0;
    sort(edge,edge+k,rule());
    for(int i=0;i<k;i++){
        int dx=ifind(edge[i].u);
        int dy=ifind(edge[i].v);
        if(dx==dy) continue;
        f[dx]=dy;
        ans+=edge[i].w;
    }
}

int main()
{
    int n;
    while(cin>>n&&n){
        for(int i=0;i<30;i++) f[i]=i;
        int w,m;
        k=0;
        char x,y;
        for(int i=0;i<n-1;i++){
            cin>>x>>m;
            for(int j=0;j<m;j++){
                cin>>y>>w;
                edge[k].u=(int)(x-'A');
                edge[k].v=(int)(y-'A');
                edge[k++].w=w;
            }
        }
        kruskal();
        cout<<ans<<endl;
    }
    return 0;
}

2.POJ - 1287(模板题)


网友的翻译我是爱了。
是个稠密图应该用prim,但是我用了kruskal(好写)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 1000000
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v,w;
}edge[maxn];
int f[maxn];
int n,m;
int ans=0;
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}

void kruskal(){
    ans=0;
    sort(edge,edge+m,rule());
    for(int i=0;i<m;i++){
        int dx=ifind(edge[i].u);
        int dy=ifind(edge[i].v);
        if(dx==dy) continue;
        f[dx]=dy;
        ans+=edge[i].w;
    }
}

int main()
{
    while(cin>>n&&n){
        cin>>m;
        for(int i=0;i<=n;i++) f[i]=i;
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        kruskal();
        cout<<ans<<endl;
    }
    return 0;
}

3.POJ 2031(生成最小树)

这个题注意一下他们之间的权值是怎么的来的就行了,也算是个板子题把

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 10010
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v;
    double w;
}edge[maxn];
struct ss{
    double x,y,z,r;
}a[maxn];
int f[maxn];
int n,m;
double ans=0;
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}

void kruskal(){
    ans=0;
    sort(edge,edge+m,rule());
    for(int i=0;i<m;i++){
        int dx=ifind(edge[i].u);
        int dy=ifind(edge[i].v);
        if(dx==dy) continue;
        f[dx]=dy;
        ans+=edge[i].w;
    }
}
double judge(ss a,ss b){
    double temp=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
    if(temp<=a.r+b.r) return 0;
    return temp-a.r-b.r;
}
int main()
{
    while(cin>>n&&n){
        m=0;
        for(int i=0;i<maxn;i++) f[i]=i;
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z,&a[i].r);
        }
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                edge[m].u=i;
                edge[m].v=j;
                edge[m++].w=judge(a[i],a[j]);
            }
        }
        kruskal();
        printf("%.3f\n",ans);
    }
    return 0;
}

4. POJ-2421

这个题有些边已经连接起来了,所以我们提前把他连好的边加到树里就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 1000000
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v,w;
}edge[maxn];
int f[maxn];
int n,m,k;
int ans=0;
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}

void kruskal(){
    ans=0;
    sort(edge,edge+k,rule());
    for(int i=0;i<k;i++){
        int dx=ifind(edge[i].u);
        int dy=ifind(edge[i].v);
        if(dx==dy) continue;
        f[dx]=dy;
        ans+=edge[i].w;
    }
}

int main()
{
    cin>>n;
    for(int i=0;i<=n;i++) f[i]=i;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            int x;
            scanf("%d",&x);
            if(i==j) continue;
            edge[k].u=i;
            edge[k].v=j;
            edge[k++].w=x;
        }
    }
    cin>>m;
    for(int i=0;i<m;i++){
        int x,y;
        cin>>x>>y;
        int dx=ifind(x);
        int dy=ifind(y);
        if(dx==dy) continue;
        f[dx]=dy;
    }
    kruskal();
    cout<<ans<<endl;
    return 0;
}

5.ZOJ - 1586(模板题)

这个题与模板题不同的一点是,每个点都有自己的花费,假设链接a b两点,则权值为ab两点之间的权值+a的花费+b的花费

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 1010
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
int a[maxn],f[maxn];
struct wazxy{
    int u,v,w;
}e[maxn*maxn];
int n,k;
int ans=0;
struct rule{
    bool operator ()(const wazxy & a,const wazxy & b){
    return a.w<b.w;
    }
};

int ifind(int x){
    if(x==f[x]) return x;
    return f[x]=ifind(f[x]);
}

void kruskal(){
    sort(e,e+k,rule());
    for(int i=0;i<k;i++){
        int dx=ifind(e[i].u);
        int dy=ifind(e[i].v);
        if(dx==dy) continue;
        else{
            ans+=e[i].w;
            f[dx]=dy;
        }
    }
}
int main()
{
    int t;
    cin>>t;
    while(t--){
        for(int i=0;i<maxn;i++) f[i]=i;
        ans=0,k=0;
        cin>>n;
        int x;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&x);
                if(i==j) continue;
                e[k].u=i;
                e[k].v=j;
                e[k++].w=x+a[i]+a[j];
            }
        }
        //for(int i=0;i<k;i++) cout<<e[i].w<<" ";
        kruskal();
        cout<<ans<<endl;
    }
    return 0;
}

6.POJ - 1789

把每个字符串看成一个点,每个点之间的权值就是他们对应不同的字符个数
这个题练习了一下prim算法,毕竟是个稠密图

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 2010
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
int n;
string s[maxn];
int maps[maxn][maxn];
int dis[maxn];
bool visited[maxn];
int dif(int x,int y){
    int ans=0;
    for(int i=0;i<7;i++){
        if(s[x][i]!=s[y][i]) ans++;
    }
    return ans;
}
struct node{
    int id,dis;
    node(int a,int b){id=a,dis=b;}
    bool operator < (const node & a)const
    {return dis>a.dis;}
};
int prim(){
    int ans=0;
    memset(dis,MaxN,sizeof(dis));
    priority_queue<node> q;
    dis[1]=0;
    q.push(node(1,0));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        int now=temp.id;
        if(visited[now]) continue;
        visited[now]=true;
        ans+=dis[now];
        for(int i=1;i<=n;i++){
            if(i==now) continue;
            int val=maps[now][i];
            if(!visited[i]&&dis[i]>val){
                dis[i]=val;
                q.push(node(i,dis[i]));
            }
        }
    }
    return ans;

}

int main()
{
    while(cin>>n&&n){
        memset(visited,false,sizeof(visited));
        for(int i=1;i<=n;i++) cin>>s[i];
        for(int i=1;i<=n;i++){
            for(int f=1;f<=n;f++){
                if(i==f) continue ;
                maps[i][f]=dif(i,f);
            }
        }
        cout<<"The highest possible quality is 1/"<<prim()<<"."<<endl;
    }

}

7.POJ - 2349(生成最小树中的最大的边权)

题意:给你n个点的二维坐标,求生成最小树中到数第k大的边权为多少
拿一个数组来记录一下边,然后sort一下输出即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 510
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v;
    double w;
}edge[maxn*maxn];
int f[maxn];
double b[maxn];
int n,m,k,cnt,cnt1;
double ans=0;
struct node{
    double x,y;
}a[maxn];
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}

void kruskal(){
    ans=0;
    sort(edge,edge+cnt,rule());
    for(int i=0;i<cnt;i++){
        int dx=ifind(edge[i].u);
        int dy=ifind(edge[i].v);
        if(dx==dy) continue;
        f[dx]=dy;
        ans+=edge[i].w;
        b[cnt1++]=edge[i].w;
    }
}
double dis(int x, int y){
    return sqrt((a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y));
}
int main()
{
    int t;
    cin>>t;
    while(t--){
        for(int i=0;i<maxn;i++) f[i]=i;
        cnt=0,cnt1=0;
        cin>>k>>m;
        for(int i=1;i<=m;i++) cin>>a[i].x>>a[i].y;
        for(int i=1;i<=m;i++){
            for(int j=1;j<=m;j++){
                if(i==j) continue ;
                edge[cnt].u=i;
                edge[cnt].v=j;
                edge[cnt++].w=dis(i,j);
            }
        }
        kruskal();
        sort(b,b+cnt1);
        printf("%.2f\n",b[cnt1-k]);
    }
    return 0;
}

8.POJ - 1751

天啦噜,这个题前期tle都tle到天上了,建议G++提交(我也不知道为什么)
存边的时候注意一下存一次就够了不要重了,不然带来的就是tle

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 1010
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v;
    double w;
}edge[maxn*maxn];
int f[maxn];
double b[maxn];
int n,m,k,cnt;
double ans=0;
struct node{
    double x,y;
}a[maxn];
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}

void kruskal(){
    sort(edge,edge+cnt,rule());
    for(int i=0;i<cnt;i++){
        int dx=ifind(edge[i].u);
        int dy=ifind(edge[i].v);
        if(dx==dy) continue;
        f[dx]=dy;
        printf("%d %d\n",edge[i].u,edge[i].v);
    }
}
inline double dis(int x, int y){
    return sqrt((a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y));
}
int main()
{
    for(int i=0;i<maxn;i++) f[i]=i;
    cnt=0;
    cin>>m;
    for(int i=1;i<=m;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
    for(int i=1;i<=m;i++){
        for(int j=i+1;j<=m;j++){
            edge[cnt].u=i;
            edge[cnt].v=j;
            edge[cnt++].w=dis(i,j);
        }
    }
    cin>>m;
    for(int i=0;i<m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        int dx=ifind(x);
        int dy=ifind(y);
        if(dx==dy) continue ;
        f[dx]=dy;
    }
    kruskal();
    return 0;
}

9.POJ-1258(模板题)

模板模板模板

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 110
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v;
    int w;
}edge[maxn*maxn];
int f[maxn];
int n,m,k,cnt;
int ans=0;
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}

void kruskal(){
    sort(edge,edge+cnt,rule());
    ans=0;
    for(int i=0;i<cnt;i++){
        int dx=ifind(edge[i].u);
        int dy=ifind(edge[i].v);
        if(dx==dy) continue;
        f[dx]=dy;
        ans+=edge[i].w;
    }
}

int main()
{
    while(cin>>m){
        for(int i=0;i<maxn;i++) f[i]=i;
        cnt=0;
        for(int i=1;i<=m;i++){
            for(int j=1;j<=m;j++){
                int x;
                scanf("%d",&x);
                if(i<=j) continue;
                edge[cnt].u=i;
                edge[cnt].v=j;
                edge[cnt++].w=x;
            }
        }
        kruskal();
        cout<<ans<<endl;
    }

    return 0;
}

10.HDU1233(模板题)

这个之前写过

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <math.h>
#include <string>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#define maxn 110
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;
int f[maxn];
struct wazxy{
    int u,v,w;
}a[maxn*maxn];

int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}
struct rule{
    bool operator()(const wazxy & a,const wazxy & b){
    return a.w<b.w;
    }
};

int main()
{
    int n;
    while(cin>>n&&n){
        int m=n*(n-1)/2;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
        }
        sort(a+1,a+m+1,rule());
        int ans=0;
        for(int i=1;i<=n;i++) f[i]=i;
        for(int i=1;i<=m;i++){
            int dx=ifind(a[i].u);
            int dy=ifind(a[i].v);
            if(dx==dy) continue;
            f[dx]=dy;
            ans+=a[i].w;
        }
        cout<<ans<<endl;
    }
    return 0;
}



11.HDU-1301

ps跟第一题一样的

12.HDU-1875

这个题注意判断一下哪些边不可取即可,这里我是在存图的时候判断的边长度是否符合题意,不符合就不加入。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 110
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v;
    double w;
}edge[maxn*maxn];
int f[maxn];
bool visited[maxn];
int n,m,k,cnt;
double ans=0;
struct node{
    double x,y;
}a[maxn];
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}
void init(){
    for(int i=0;i<maxn;i++) f[i]=i;
    memset(visited,false,sizeof(visited));
    cnt=0,ans=0;
}
double dis(int x,int y){
    double temp=(a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y);
    temp=sqrt(temp);
    if(temp>1000||temp<10) return -1;
    return temp;
}
void kruskal(){
    sort(edge,edge+cnt,rule());
    for(int i=0;i<cnt;i++){
        int dx=ifind(edge[i].u);
        int dy=ifind(edge[i].v);
        if(dx==dy) continue;
        ans+=edge[i].w;
        visited[edge[i].u]=true;
        visited[edge[i].v]=true;
        f[dx]=dy;
    }
}

int main()
{
    int t;
    cin>>t;
    while(t--){
        init();
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i].x>>a[i].y;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                double temp=dis(i,j);
                if(temp==-1) continue;
                edge[cnt].u=i;
                edge[cnt].v=j;
                edge[cnt++].w=dis(i,j);
            }
        }
        kruskal();
        bool flag=true;
        for(int i=1;i<=n;i++){
            if(!visited[i]) flag=false;
            //cout<<visited[i]<<endl;
        }
        if(flag==false) cout<<"oh!"<<endl;
        else printf("%.1f\n",ans*100);
    }

    return 0;
}

13.POJ-3026(bfs+kruskal)

这个题说难吧,他不难,就是挺麻烦的。
这个题先给你些许个点,每个点的距离需要你自己bfs计算出来。
我做这个题的时候出了好多bug,但是都是小问题,很快就调好了
注意:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn 510
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
ll mod = 998244353;
using namespace std;
struct wazxy{
    int u,v;
    int w;
}edge[maxn*maxn];
char s[maxn];
int n,m,num,rem,cnt,ans;
int a[maxn][maxn],f[maxn];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
bool visited[maxn][maxn];
struct node{
    int x,y,steps;
    node(int a,int b,int c){x=a,y=b,steps=c;}
};
struct rule{
    bool operator()(const wazxy &a,const wazxy & b){
    return a.w<b.w;
    }
};
int ifind(int x){
    if(x==f[x]) return x;
    else return f[x]=ifind(f[x]);
}

void init(){
    memset(a,-1,sizeof(a));
    for(int i=0;i<maxn;i++) f[i]=i;
    num=1,cnt=0;
}

void bfs(int x,int y){
    queue<node> q;
    visited[x][y]=true;
    q.push(node(x,y,0));
    while(!q.empty()){
        node temp=q.front();
        q.pop();
        if(a[temp.x][temp.y]>0&&a[temp.x][temp.y]!=rem){
            edge[cnt].u=rem;
            edge[cnt].v=a[temp.x][temp.y];
            edge[cnt++].w=temp.steps;
           // cout<<a[temp.x][temp.y]<<endl;
        }
        for(int i=0;i<4;i++){
            int nx=temp.x+dx[i],ny=temp.y+dy[i];
            if(!visited[nx][ny]&&a[nx][ny]>=0){
                visited[nx][ny]=true;
              // cout<<nx<<" "<<ny<<endl;
                q.push(node(nx,ny,temp.steps+1));
            }
        }
    }
}

void kruskal(){
    sort(edge,edge+cnt,rule());
    ans=0;
    for(int i=0;i<cnt;i++){
        int xx=ifind(edge[i].u);
        int yy=ifind(edge[i].v);
        if(xx==yy) continue;
        ans+=edge[i].w;
        f[xx]=yy;
    }
}

int main()
{
    int t;
    cin>>t;
    while(t--){
        int n,m;
        init();
        cin>>m>>n;
        gets(s);
        for(int i=1;i<=n;i++){
            gets(s);
            for(int j=0;j<m;j++){
                if(s[j]==' ') a[i][j+1]=0;
                else if(s[j]=='A'||s[j]=='S') a[i][j+1]=num++;
            }
        }

// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++){
// cout<<a[i][j]<<" ";
// }
// cout<<endl;
// }

        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(a[i][j]>0){
                    rem=a[i][j];
                    memset(visited,false,sizeof(visited));
                    bfs(i,j);
                 // cout<<"1"<<endl;
                }
            }
        }
        kruskal();
        cout<<ans<<endl;
    }
    return 0;
}