http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3204
题意:给出一个图的链接矩阵,要求按照字典序最小的情况输出连接边
Prim算法加father数组记录父亲节点,更新时在距离相同的情况下维护父亲节点值最小,然后根据父亲节点和当前节点的大小创建边,最后排序并输出
#include<iostream>
#include<cstdio>
#include<set>
#include<string>
#include<string.h>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<cctype>
#include<algorithm>
#include<sstream>
#include<utility>
#define mt(a) memset(a,0,sizeof (a))
#define fl(a,b,c) fill(a,b,c)
#define SWAP(a,b,t) (t=a,a=b,b=t)
#define inf 1000000000+7
using namespace std;
typedef long long ll;
int MaxVal;
int vis[120];
int dis[120];
int graph[120][120];
int fa[120];
typedef struct aaa
{
int in, out;
}aaa;
aaa ans[120];
int cnt;
bool com(aaa x, aaa y)
{
if (x.in != y.in)return x.in < y.in;
return x.out < y.out;
}
void prim()
{
mt(vis);
mt(ans);
mt(fa);
cnt = 0;
fill(dis, dis+MaxVal,inf);
int pos, getfa, i, j,minn;
pos = 0; vis[0] = 1;
for (int i = 0; i < MaxVal; i++)
{
fa[i] = pos;
dis[i] = graph[pos][i];
}
for (int i = 0; i < MaxVal-1; i++)
{
pos = -1; minn = inf;
for (int j = 0; j < MaxVal; j++)
{
if (!vis[j] && (dis[j] < minn||(dis[j] == minn&&fa[j]<pos)))
{
minn = dis[pos = j];
}
}
if (pos == -1)break;
if (fa[pos] < pos){
ans[cnt].in = fa[pos] + 1;
ans[cnt++].out = pos + 1;
}
else
{
ans[cnt].in = pos + 1;
ans[cnt++].out = fa[pos] + 1;
}
vis[pos] = 1;
for (int j = 0; j < MaxVal; j++)
{
if (!vis[j] && (graph[pos][j] < dis[j]) || (graph[pos][j] == dis[j] && pos<fa[j]))
{
dis[j] = graph[pos][j];
fa[j] = pos;
}
}
}
}
int main()
{
int T;
cin >> T;
while (T--)
{
cin >> MaxVal;
mt(graph);
for (int i = 0; i < MaxVal; i++)
{
for (int j = 0; j < MaxVal; j++)
{
scanf("%d", &graph[i][j]);
if (!graph[i][j])graph[i][j] = inf;
}
}
prim();
int flag = 1;
for (int i = 1; i < MaxVal; i++)if (!vis[i])flag = 0;
if (!flag){ printf("-1\n"); continue; }
sort(ans, ans + cnt, com);
for (int i = 0; i < cnt; i++)
{
if (i)printf(" ");
printf("%d %d", ans[i].in, ans[i].out);
}
printf("\n");
}
return 0;
}