最大生成树+图的连通性

时间:2021-11-27 12:59:10

POJ 2377

  此题为最大生成树问题,与最小生成树类似.采用kruskal()算法

    最小生成树是将边从小到大排序,此题只要将边从大到小排序就ok了,

   考虑到重边的存在,用prim()算法的话可能会出错;

  另外,由于我没完整看完题意,没有发现还要判断图是否连通,不连通时要输出-1,导致wa了一次.

  对于连通性的判断,由于前面已经用过并查集了,只需要将任意一个顶点与其他每个顶点判断一次就ok了.

  对于连通性的判断,也可以用dfs+color数组标记

  其他注意点:此题为无向边,初始化es[E]结构题数组时,要加倍,否则会re.

  不说废话了,上码

  

/*
* Created:     2016年03月29日 08时57分11秒 星期二
* Author:      Akrusher
*
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define in(n) scanf("%d",&(n))
#define in2(x1,x2) scanf("%d%d",&(x1),&(x2))
#define inll(n) scanf("%I64d",&(n))
#define inll2(x1,x2) scanf("%I64d%I64d",&(x1),&(x2))
#define inlld(n) scanf("%lld",&(n))
#define inlld2(x1,x2) scanf("%lld%lld",&(x1),&(x2))
#define inf(n) scanf("%f",&(n))
#define inf2(x1,x2) scanf("%f%f",&(x1),&(x2))
#define inlf(n) scanf("%lf",&(n))
#define inlf2(x1,x2) scanf("%lf%lf",&(x1),&(x2))
#define inc(str) scanf("%c",&(str))
#define ins(str) scanf("%s",(str))
#define out(x) printf("%d\n",(x))
#define out2(x1,x2) printf("%d %d\n",(x1),(x2))
#define outf(x) printf("%f\n",(x))
#define outlf(x) printf("%lf\n",(x))
#define outlf2(x1,x2) printf("%lf %lf\n",(x1),(x2));
#define outll(x) printf("%I64d\n",(x))
#define outlld(x) printf("%lld\n",(x))
#define outc(str) printf("%c\n",(str))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define mem(X,Y) memset(X,Y,sizeof(X));
typedef vector<int> vec;
typedef long long ll;
typedef pair<int,int> P;
const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const bool AC=true;

struct edge{
    int from,to,cost;
};
bool cmp(const edge& e1,const edge& e2){
    return e1.cost>e2.cost;
}
edge es[20005*2];//无向边最大值加倍
int par[1005];
int ran[1005];
void init(int n){
    rep(i,0,n){
    par[i]=i;
    ran[i]=0;
    }
}
int find(int x){
    if(par[x]==x) return x;
    return par[x]=find(par[x]);
}
void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y) return;
    if(ran[x]<ran[y]) par[x]=y;
    else{
    par[y]=x;
    if(ran[x]==ran[y])
    ran[x]++;
    }
}
bool same(int x,int y){
    return find(x)==find(y);
}
int main()
{
    int n,m,a,b,c,k;
    in2(n,m);
    k=0;
    while(m--){
    in2(a,b);
    in(c);
    a--;b--;
    es[k].from=a;
    es[k].to=b;
    es[k++].cost=c;
    es[k].from=b;
    es[k].to=a;
    es[k++].cost=c;
    }
    //最大生成树
    sort(es,es+k,cmp);//边数是原来的两倍,为k,从大到小排序
    init(n);
    int res=0;
    rep(i,0,k){
    if(!same(es[i].from,es[i].to)){
    res+=es[i].cost;
    unite(es[i].from,es[i].to);
    }
    }
    bool flag=true;
    rep(i,1,n){
    if(!same(0,i)){
    flag=false;
    break;
    }
    }
    if(flag)
    out(res);
    else{
    out(-1);
    }
    return 0;
}