1.多路径最短路用费用流实现

2.每个点要被强制流过->拆点成弧并且加下界为1的容量

3.所有点向比它编号大的点连边

#include <iostream>
#include <stdio.h>
#include <queue>
#include <math.h>
#include <string.h>
using namespace std;
#define V 1500
#define E 1000000
#define inf 0x3F3F3F3F
int n,m;
int vis[V];
int dist[V];
int pre[V];
#define left(x) (x*2-1)
#define right(x) (x*2)

int map[V][V];
int s,start,end,super_start,super_end,top;

struct Edge{
    int u,v,c,cost,next;
}edge[E];
int head[V],cnt;
void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int c,int cost){
    edge[cnt].u=u;edge[cnt].v=v;edge[cnt].cost=cost;

    edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++;

    edge[cnt].u=v;edge[cnt].v=u;edge[cnt].cost=-cost;
    edge[cnt].c=0;edge[cnt].next=head[v];head[v]=cnt++;
}

bool spfa(int begin,int end){
    int u,v;
    queue<int> q;

    for(int i=0;i<=end+2;i++){
        pre[i]=-1;
        vis[i]=0;
        dist[i]=inf;
    }
    vis[begin]=1;
    dist[begin]=0;
    q.push(begin);

    while(!q.empty()){

        u=q.front();
        q.pop();
        vis[u]=0;

        for(int i=head[u];i!=-1;i=edge[i].next){
            if(edge[i].c>0){
                v=edge[i].v;
                if(dist[v]>dist[u]+edge[i].cost){
                    dist[v]=dist[u]+edge[i].cost;
                    pre[v]=i;
                    if(!vis[v]){
                        vis[v]=true;
                        q.push(v);
                    }
                }
            }
        }

    }

    return dist[end]!=inf;
}

int MCMF(int begin,int end){
    int ans=0,flow;
    int flow_sum=0;

    while(spfa(begin,end)){

        flow=inf;
        for(int i=pre[end];i!=-1;i=pre[edge[i].u])
            if(edge[i].c<flow)
                flow=edge[i].c;
        for(int i=pre[end];i!=-1;i=pre[edge[i].u]){
            edge[i].c-=flow;
            edge[i^1].c+=flow;
        }
        ans+=dist[end];
        flow_sum+=flow;

    }
    return ans;
}
void build(){
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            map[i][j]=i==j?0:inf;
    for(int i=0,a,b,c;i<m;i++){
        scanf("%d%d%d",&a,&b,&c);
        map[a][b]=map[b][a]=min(map[a][b],c);
    }
    for(int k=0;k<=n;k++)
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                map[i][j]=min(map[i][j],map[i][k]+map[k][j]);


    start=0,end=2*n+1,top=end+1;
    super_start=top+1,super_end=top+2;

    init();
    //每个点要被强制流过->拆点成弧并且加下界为1的容量
    for(int i=1;i<=n;i++){
        addedge(super_start,right(i),1,0);//加下界为1的容量
        addedge(left(i),super_end,1,0);//加下界为1的容量
        addedge(start,left(i),inf,map[0][i]);
        addedge(right(i),end,inf,map[0][i]);
    }
    //所有点向比它编号大的点连边
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            addedge(right(i),left(j),1,map[i][j]);
    //警察队数
    addedge(top,start,s,0);
    addedge(end,top,inf,0);
}
int main(){
    while(scanf("%d%d%d",&n,&m,&s),n+m+s){
        build();
        int res=MCMF(super_start,super_end);
        printf("%d\n",res);
    }
    return 0;
}