https://codeforces.com/gym/102391/problem/I
学习自https://blog.csdn.net/crazy_ac/article/details/8816877
板题做了一个下午,头快想烂了
首先找到图的绝对中心,然后由于边权不为1,所以把所有边权都*2,然后中心到其他点的距离也会是整数了,确定中心后就从u,v开始跑,记得dis[u],dis[v]要设为真正的初始值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=510;
const ll inf=1ll<<61;
int n,m,s1,s2,tot;ll ans;
int frm[maxl],ansx[maxl],ansy[maxl];
ll dis[maxl];
ll d[maxl][maxl],w[maxl][maxl],rk[maxl][maxl];
typedef pair<ll,int> p;
priority_queue<p,vector<p>,greater<p> >q;
vector<int> e[maxl];
bool vis[maxl];
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
w[i][j]=d[i][j]=inf;
for(int i=1;i<=n;i++)
w[i][i]=d[i][i]=0;
int u,v,l;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&l);l*=2;
d[u][v]=d[v][u]=w[u][v]=w[v][u]=l;
e[u].push_back(v);e[v].push_back(u);
}
}
inline ll findct()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
rk[i][j]=j;
for(int j=1;j<=n;j++)
for(int k=j+1;k<=n;k++)
if(d[i][rk[i][j]]>d[i][rk[i][k]])
swap(rk[i][j],rk[i][k]);
}
ll mi=inf;
for(int u=1;u<=n;u++)
for(int v:e[u])
{
if(u>v)
continue;
if((d[u][rk[u][n]]*2)<mi)
{
dis[s1]=dis[s2]=inf;
mi=d[u][rk[u][n]]*2,s1=s2=u,dis[u]=0;
}
if((d[v][rk[v][n]]*2)<mi)
{
dis[s1]=dis[s2]=inf;
mi=d[v][rk[v][n]]*2,s1=s2=v,dis[v]=0;
}
for(int last=n,i=n-1;i;i--)
if(d[v][rk[u][i]]>d[v][rk[u][last]])
{
ll tmp=d[u][rk[u][i]]+d[v][rk[u][last]]+w[u][v];
if(tmp<mi)
{
dis[s1]=dis[s2]=inf;
mi=tmp;s1=u,s2=v;
dis[s1]=tmp/2-d[u][rk[u][i]];
dis[s2]=w[u][v]-dis[s1];
}
last=i;
}
}
return mi/2;
}
inline void mainwork()
{
for(int i=1;i<=n;i++)
dis[i]=inf,vis[i]=false;
ans=findct();
if(s1!=s2)
q.push({dis[s1],s1}),q.push({dis[s2],s2});
else
q.push({dis[s1],s1});
tot=0;
if(s1!=s2)
++tot,ansx[1]=s1,ansy[1]=s2;
int u;p d;
while(q.size())
{
d=q.top();q.pop();
u=d.second;
if(d.first!=dis[u] || vis[u])
continue;
vis[u]=true;
if(u!=s1 && u!=s2)
++tot,ansx[tot]=frm[u],ansy[tot]=u;
for(int v:e[u])
{
if(dis[v]<=dis[u]+w[u][v])
continue;
dis[v]=dis[u]+w[u][v];frm[v]=u;
q.push({dis[v],v});
}
}
}
inline void print()
{
printf("%lld\n",ans);
for(int i=1;i<=n-1;i++)
printf("%d %d\n",ansx[i],ansy[i]);
}
int main()
{
prework();
mainwork();
print();
return 0;
}