判断够不够成环,成环最小,每个点贡献2次,如果还有边全连最小。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int inf = 0x3f3f3f3f;
#define LL long long
#define N 1100
struct node
{
int a, val;
}w[N];
bool cmp(node a, node b)
{
return a.val < b.val;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n, m, ans = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &w[i].val);
w[i].a = i;
ans += w[i].val;
}
if (n == 2 || m < n)
{
printf("-1\n");
continue;
}
ans *= 2;
sort(w + 1, w + n + 1, cmp);
m -= n;
int temp = w[1].val + w[2].val;
ans += m * temp;
cout << ans << endl;
for (int i = 1; i <= m; i++)
{
printf("%d %d\n", w[1].a, w[2].a);
}
for (int i = 1; i < n; i++)
{
printf("%d %d\n", w[i].a, w[i + 1].a);
}
printf("%d %d\n", w[n].a, w[1].a);
}
return 0;
}
判断头或尾,第一个度为1,第二个度为2,剩下度全赋为3。
然后拓扑排序就好。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define N 100010
struct node
{
int u,v,nxt;
}e[6*N];
int head[N],cnt;
int fir,sec;
void add(int u,int v)
{
e[++cnt].v=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
int vis[N],f[N];
void tuopu()
{
queue<int>q;
q.push(fir);
int u,v;
while(!q.empty())
{
u=q.front(),q.pop();
f[fir]=1;
printf("%d ",u);
for(int i=head[u];i;i=e[i].nxt)
{
v=e[i].v;
if(f[v])continue;
vis[v]--;
if(vis[v]==1)
{
q.push(v);
}
}
}
cout<<endl;
}
int main()
{
int n;
scanf("%d",&n);
int x,y,z;
for(int i=1;i<=n-2;i++)
{
scanf("%d%d%d",&x,&y,&z);
vis[x]++,vis[y]++,vis[z]++;
add(x,y),add(y,x);
add(x,z),add(z,x);
add(y,z),add(z,y);
}
for(int i=1;i<=n;i++)
{
if(vis[i]==1)
{
fir=i;
for(int j=head[i];j;j=e[j].nxt)
{
if(vis[e[j].v]==2)
{
sec=e[j].v;
break;
}
}
break;
}
}
for(int i=1;i<=n;i++)
{
if(i==fir||i==sec)continue;
vis[i]=3;
}
//for(int i=1;i<=n;i++)cout<<vis[i]<<" ";
tuopu();
return 0;
}