First, we consider what the last k routes might look like:
It must be 0 - > X1 - > ->xn,x1< x2<… < xn. That is to say, we only need up to k such paths to cover all points. We can certainly make all visits legal by arranging the order. Each point can go through many times. We think that we need to preprocess the shortest distance between two points and meet the legal conditions. floyd pretreatment can be used. When mp[i][k]+mp[k][j] is used to update mp[i][j], ensure that K < j is enough. The meaning of mp[i][j] is to visit I for the first time. The location of the next first visit of this route is the minimum cost of j. If we force I - > j, I < j, then we get a DAG
Now the problem is to cover all the points of DAG with up to k paths, which requires the path edge weight and minimum. It can be built as follows: each point can be divided into input point i and output point i+n (0 only has output point).
S - > 0, k, 0. Indicates the maximum number of k paths
S - > i + N, 1,0, after the first visit to i
i - > t, 1,0. Indicates the first time to i.
Each edge I - > j, MP [i] [j], edge I + n - > j, 1, MP [i] [j]. The first time I visited j
Full flow in this figure is the legal scheme, so it's good to directly run the minimum cost and maximum flow.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 310
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m,K,h[N],num=1,dis[N],path[N],S=301,T=302,mp[200][200],ans=0;
bool inq[N];
struct edge{
int to,next,c,w;
}data[25000];
inline void add(int x,int y,int w,int c){
data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].w=w;data[num].c=c;
data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].w=0;data[num].c=-c;
}
inline bool spfa(){
deque<int>q;memset(path,0,sizeof(path));memset(dis,inf,sizeof(dis));
q.push_back(S);dis[S]=0;inq[S]=1;
while(!q.empty()){
int x=q.front();q.pop_front();inq[x]=0;
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;if(!data[i].w) continue;
if(dis[x]+data[i].c<dis[y]){
dis[y]=dis[x]+data[i].c;path[y]=i;
if(!inq[y]){
if(!q.empty()&&dis[y]<dis[q.front()]) q.push_front(y);
else q.push_back(y);inq[y]=1;
}
}
}
}return path[T];
}
int main(){
// freopen("a.in","r",stdin);
n=read();m=read();K=read();add(S,0,K,0);memset(mp,inf,sizeof(mp));
for(int i=1;i<=n;++i) add(S,i+n,1,0),add(i,T,1,0);
while(m--){
int x=read(),y=read();mp[x][y]=mp[y][x]=min(read(),mp[x][y]);
}for(int k=0;k<=n;++k)
for(int i=0;i<=n;++i)
for(int j=0;j<=n;++j){
if(k>j) continue;
mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
}
for(int i=1;i<=n;++i) if(mp[0][i]!=inf) add(0,i,1,mp[0][i]);
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j){
if(mp[i][j]==inf) continue;
add(i+n,j,1,mp[i][j]);
}
while(spfa()){
int now=T,low=inf;
while(path[now]) low=min(low,data[path[now]].w),now=data[path[now]^1].to;
ans+=low*dis[T];now=T;
while(path[now]) data[path[now]].w-=low,data[path[now]^1].w+=low,now=data[path[now]^1].to;
}printf("%d\n",ans);
return 0;
}