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 }

 

你可能感兴趣的:(最小生成树)