zoj 3204 最小生成树,输出字典序最小的解

 注意排序即可

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 using namespace std;
  8 #define for0n for(i=0;i<n;i++)
  9 #define for1n for(i=1;i<=n;i++)
 10 #define for0m for(i=0;i<m;i++)
 11 #define for1m for(i=1;i<=m;i++)
 12 #define cl(a) memset(a,0,sizeof(a))
 13 #define w12 while(scanf("%d%d",&n,&m)!=EOF)
 14 #define s12 scanf("%d%d",&n,&m);
 15 #define sa scanf("%d",a[i]);
 16 #define sb scanf("%d",b[i]);
 17 #define qq printf("*****\n");
 18 int n,m,tt;
 19 const int MAXN = 110;
 20 const int MAXM=10000;//最大边数
 21 int F[MAXN];//并查集使用
 22 struct Edge
 23 {
 24     int u,v,w;
 25 }edge[MAXN*MAXN];//存储边的信息,包括起点/终点/权值
 26 Edge anss[MAXN*MAXN];
 27 int tol;//边数,加边前赋值为0
 28 void addedge(int u,int v,int w)
 29 {
 30     edge[tol].u=u;
 31     edge[tol].v=v;
 32     edge[tol++].w=w;
 33 }
 34 bool cmp(Edge a,Edge b)
 35 {//排序函数,讲边按照权值从小到大排序
 36     if(a.w!=b.w)return a.w<b.w;
 37     else if(a.u!=b.u)return a.u<b.u;
 38     else return a.v<b.v;
 39 }
 40 int find(int x)
 41 {
 42     if(F[x]==-1)return x;
 43     else return F[x]=find(F[x]);
 44 }
 45 int cnt=0;//计算加入的边数
 46 int Kruskal(int n)//传入点数,返回最小生成树的权值,如果不连通返回-1
 47 {
 48     memset(F,-1,sizeof(F));
 49     sort(edge,edge+tol,cmp);
 50     int ans=0;
 51     for(int i=0;i<tol;i++)
 52     {
 53         int u=edge[i].u;
 54         int v=edge[i].v;
 55         int w=edge[i].w;
 56         int t1=find(u);
 57         int t2=find(v);
 58         if(t1!=t2)
 59         {
 60             ans+=w;
 61             anss[cnt]=edge[i];
 62             F[t1]=t2;
 63             cnt++;
 64         }
 65         if(cnt==n-1)break;
 66     }
 67     if(cnt<n-1)return -1;//不连通
 68     else return ans;
 69 }
 70 bool cmp2(Edge a,Edge b)
 71 {
 72     if(a.u!=b.u)return a.u<b.u;
 73     else return a.v<b.v;
 74 }
 75 int main()
 76 {
 77     #ifndef ONLINE_JUDGE
 78     freopen("1.in","r",stdin);
 79     #endif
 80     int T;
 81     scanf("%d",&T);
 82     while(T--)
 83     {
 84         scanf("%d",&n);
 85         tol=0;
 86         cnt=0;
 87         int w;
 88         for(int i=1;i<=n;i++)
 89           for(int j=1;j<=n;j++)
 90           {
 91               scanf("%d",&w);
 92               if(j<=i)continue;
 93               if(w==0)continue;
 94               addedge(i,j,w);
 95           }
 96         int ff=Kruskal(n);
 97         if(ff==-1)
 98         {
 99             printf("-1\n");
100             continue;
101         }
102         else
103         {
104             sort(anss,anss+cnt,cmp2);
105             for(int i=0;i<cnt-1;i++)
106               printf("%d %d ",anss[i].u,anss[i].v);
107             printf("%d %d\n",anss[cnt-1].u,anss[cnt-1].v);
108         }
109     }
110     return 0;
111 }

 

转载于:https://www.cnblogs.com/cnblogs321114287/p/4393758.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值