Description
Sample Input
3
0 2 2
2 0 2
2 2 0
Sample Output
2
2 3 2
1 3 2
题解:
即将完全图连边 跑一遍最大生成树(只需修改最小生成树判断条件)
每次连边都连向之前的联通块且该边为当前最小 所以答案正确
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int Maxn= 1000;
int f[Maxn][Maxn];
inline int read()
{
char ch=getchar();int i=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
return i*f;
}
struct node
{
int to;
int val;
node(int x,int val):to(x),val(val){}
friend inline bool operator <(const node &a,const node &b) {
return a.val<b.val;
}
};
vector<node>edge[Maxn];
vector<node>edge2[Maxn];
priority_queue<node>q;
int dis[Maxn],match[Maxn];
ll dis2[Maxn];
int n;
bool vis[Maxn];
void display(const vector<node>& vec) {
for (auto i: vec) {
cout << i.to << ' ' << i.val << endl;
}
cout << endl;
}
inline void Insert(int x,int y,int z)
{
edge[x].push_back(node(y,z));
edge[y].push_back(node(x,z));
}
inline void InsertEdge2(int x,int y,int z)
{
edge2[x].push_back(node(y,z));
edge2[y].push_back(node(x,z));
}
inline void Prim()
{
dis[1]=0;
q.push(node(1, 0));
for(int i = 1; i <= n; i++)
{
while(!q.empty() && vis[q.top().to]) q.pop();
node tmp = q.top();
q.pop();
int now = tmp.to;
vis[now] = 1;
int siz = edge[now].size();
for(int v,e = 0; e < siz; e++) {
v = edge[now][e].to;
int va = edge[now][e].val;
if (!vis[v])
{
if(dis[v] < va)
{
dis[v] = va;
match[v] = now;
q.push(node(v, va));
}
}
}
}
}
inline bool judge()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(f[i][j]!=f[j][i])return true;
return false;
}
inline void Dfs(int now,int f)
{
int siz=edge2[now].size();
for(int v,e=0;e<siz;e++)
{
v=edge2[now][e].to;
if(v!=f)
{
dis2[v]=min(dis2[now], (ll)edge2[now][e].val);
Dfs(v,now);
}
}
}
inline bool judgevaild()
{
for(int i=1;i<=n;i++) {
if(match[i])
InsertEdge2(i,match[i],dis[i]);
}
for(int i=1;i<=n;i++) {
memset(dis2,0x3f,sizeof(dis2));
Dfs(i,0);dis2[i]=0;
for(int j=1;j<=n;j++)
{
if(j==i)continue;
if(dis2[j] != f[i][j])return true;
}
}
return false;
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
f[i][j]=read();
if(i!=j) Insert(i, j, f[i][j]);
}
if(judge()) cout<<-1;
else
{
Prim();
if(judgevaild())cout<<-1;
else
{
cout<<n-1<<endl;
for(int i=1;i<=n;i++)
{
if(match[i])
printf("%d %d %d\n",i,match[i],dis[i]);
}
}
}
return 0;
}