#include<bits/stdc++.h>
using namespace std;

const int N = 510;
int g[N][N];
int dist[N], st[N], pre[N];
int n, m;
void prim()
{
    memset(dist, 0x3f, sizeof dist);
    int res = 0;
    dist[1] = 0;
    for(int i = 0; i < n; i++)
    {
        int x = -1;
        for(int j = 1; j <= n; j++)
        {
            if(!st[j] && (x == -1 || dist[j] < dist[x]))
                x = j;
        }

        if(dist[x] == 0x3f3f3f3f)
        {
            cout << "impossible";
            return;
        }

        st[x] = 1;
        res += dist[x];
        for(int j = 1; j <= n; j++)
        {
            if(dist[j] > g[x][j] && !st[j])
            {
                dist[j] = g[x][j];
                pre[j] = x;
            }
        }
    }
    cout << res;

}

void getPath()
{
    for(int i = n; i > 1; i--)
    {
        cout << i << " " << pre[i] << " " << endl;
    }
}

int main()
{
    memset(g, 0x3f, sizeof g);
    cin >> n >> m;
    while(m --)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    prim();
    //getPath();
    return 0;
}


/*
每次将离连通部分最近的点和点对应的边加入到连通部分.

*/


#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10, M = 2e5 + 10, INF = 0x3f3f3f3f;

int n, m;
int fa[N];

struct Edge{
    int a, b, w;

    bool operator < (const Edge &W) const{
        return w < W.w;
    }
}g[M];

int find(int x)
{
    if(fa[x] == x) return fa[x];
    return fa[x] = find(fa[x]);
}

int kruskal()
{
    sort(g, g + m);

    for(int i = 1; i <= n; i++) fa[i] = i;

    int res = 0, cnt = 0;
    for(int i = 0; i < m; i++)
    {
        int a = g[i].a, b = g[i].b, w = g[i].w;
        a = find(a), b = find(b);
        if(a != b)
        {
            fa[a] = b;
            res += w;
            cnt ++;
        }
    }
    if(cnt < n - 1) return INF;
    return res;
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[i] = {a, b, c};
    }

    int t = kruskal();
    if(t == INF) cout << "impossible";
    else cout << t;
    return 0;
}

/*
原理:按照所有边的权值从小到大排序,一一枚举。
如果选择的这个边和之前选择所有边不构成回路,就选,否则,舍去。
直到选择了n-1条边为止。

回路: 边连接两个点已经连通了。 并查集判断所选边的两个点是否已经在同一个连通块
*/

0 条评论

目前还没有评论...