下面贴出代码 和 当时写题时犯的错误 ,当时查了一下krusral算法的大致思路
//采用最小生成树算法krusral 用并查集查询是否已经连通
//将所有的边按照权值从小到大排序,可以用优先队列来储存边
//接下来初始化每个点为独立的一个集合
//从边集中选者最短的一条边且这条边不会使得俩个点能形成一个环
//就是说这条边的两个端点不会在同一个连通分量中
//错误一 没有看清题目输出要求 漏掉了 边的个数
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=1000+10;
const int maxm=15000+10;
struct edge
{
int u;
int v;
int value;
bool operator < (const edge & t) const
{
return value>t.value||(value==t.value&&u>t.u)||
(value==t.value&&u==t.u&&v>t.v);
}
};
int pa[maxn];//i 的根节点
priority_queue<edge> pq;//边集的优先队列
int findset(int x){return pa[x]!=x?pa[x]=findset(pa[x]):x; }//并查集
int main()
{
int n,m;//点的个数 和 边的个数
int ans=0,ansnum=0;//最大值和最大值的个数
queue<edge> ansp;//连接的边集
scanf("%d %d",&n,&m);
//并查集初始化 ,使得每个点都单独成为一个集合
for(int i=1;i<=n;i++)
{
pa[i]=i;
}
//读入边 按照优先队列 的循序来储存 也可以排序来做 ,前面定义了一个<
for(int i=0;i<m;i++)
{
edge t;//读入时的一个临时边
scanf("%d %d %d",&t.u,&t.v,&t.value);
pq.push(t);
}
//fruskal算法 生成最小生成树
while(!pq.empty())
{
int fu,fv;
edge t=pq.top();
pq.pop();
fu=findset(t.u);
fv=findset(t.v);
//测试 printf("%d %d %d\n",t.u,t.v,t.value);
if(fu!=fv)//如果两个点不在同一个集合里 则可以加上这条边
{
ansp.push(t);//加入到答案序列中
ansnum++;
pa[fv]=fu;//合并集合
ans=max(ans,t.value);
}
if(ansnum>=n-1) break;
}
printf("%d\n%d\n",ans,ansnum);
while(!ansp.empty())
{
edge t=ansp.front();
ansp.pop();
printf("%d %d\n",t.u,t.v);
}
return 0;
}