最小生成树,输出字典序最小的解。
先排序,用kruscal算法,输出的时候按照字典序排序。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100+5;
struct Edge{
int from, to;
int w;
}edge[N*N];
Edge ans[N*N];
int father[N];
int tol, cnt;
void add_edge(int u, int v, int w)
{
edge[tol].from=u;
edge[tol].to=v;
edge[tol].w=w;
tol++;
}
bool cmp1(Edge a, Edge b)
{
if(a.w!=b.w) return a.w < b.w;
if(a.from != b.from) return a.from < b.from;
return a.to < b.to;
}
bool cmp2(Edge a, Edge b)
{
if(a.from != b.from) return a.from < b.from;
return a.to < b.to;
}
int find(int x)
{
if(father[x] == -1) return x;
return father[x]=find(father[x]);
}
void kruscal()
{
memset(father,-1,sizeof(father));
cnt=0;//加入最小生成树的边数
for(int k=0;k<tol;k++){
int u=edge[k].from;
int v=edge[k].to;
u=find(u); v=find(v);
if(u!=v){
ans[cnt++]=edge[k];
father[u]=v;
}
}
}
void init()
{
tol=0; cnt=0;
memset(edge,0,sizeof(edge));
}
int main()
{
int T, n;
cin >> T;
while(T--){
init();
cin >> n;
int w;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin >> w;
if(j<=i || w==0) continue;
add_edge(i,j,w);
}
sort(edge,edge+tol,cmp1);
kruscal();
if(cnt!=n-1) {
printf("-1\n");
continue;
}
sort(ans,ans+cnt,cmp2);
for(int i=0;i<cnt-1;i++)
printf("%d %d ",ans[i].from, ans[i].to);
printf("%d %d\n",ans[cnt-1].from,ans[cnt-1].to);
}
return 0;
}