上下界最小费用可行流,有tm重边,真傻逼
就是$$i->i‘:(1,inf,0)$$
$$i‘->j:(0,inf,w)$$
$$S->0:(0,num,0)$$
$$i‘->T:(0,inf,0)$$
然后智障的建图就好了。
之后顺便看了看达哥的floyed总结,深刻理解了floyed。
每一层k的循环就是更新i->j路径上经过不大于k的点的最短路(i,j可以大于k,但路径上其他点不行)。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #define N 350 8 #define inf 0x7fffffff 9 using namespace std; 10 int n,m,num,S,T,SS,TT; 11 int e=2,head[N]; 12 struct edge{ 13 int u,v,f,w,next; 14 }ed[N*N*4]; 15 void add(int u,int v,int f,int w){ 16 ed[e].u=u;ed[e].v=v;ed[e].f=f;ed[e].w=w; 17 ed[e].next=head[u];head[u]=e++; 18 ed[e].u=v;ed[e].v=u;ed[e].f=0;ed[e].w=-w; 19 ed[e].next=head[v];head[v]=e++; 20 } 21 int dis[N],from[N]; 22 bool vis[N]; 23 bool spfa(){ 24 memset(dis,0x3f,sizeof dis); 25 memset(from,0,sizeof from); 26 memset(vis,0,sizeof vis); 27 queue<int> q; 28 q.push(S);dis[S]=0; 29 while(!q.empty()){ 30 int x=q.front();q.pop();vis[x]=0; 31 for(int i=head[x];i;i=ed[i].next){ 32 int v=ed[i].v; 33 if(ed[i].f&&dis[v]>dis[x]+ed[i].w){ 34 dis[v]=dis[x]+ed[i].w;from[v]=i; 35 if(!vis[v]){vis[v]=1;q.push(v);} 36 } 37 } 38 } 39 return from[T]; 40 } 41 int work(){ 42 int ans=0; 43 while(spfa()){ 44 int F=inf; 45 for(int i=from[T];i;i=from[ed[i].u]) 46 F=min(F,ed[i].f); 47 for(int i=from[T];i;i=from[ed[i].u]) 48 ans+=F*ed[i].w,ed[i].f-=F,ed[i^1].f+=F; 49 } 50 return ans; 51 } 52 int g[N][N]; 53 int main(){//i->i‘:(1,inf,0) i‘->j:(0,inf,w) S->0:(0,num,0) i‘->T:(0,inf,0) 54 memset(g,0x3f,sizeof g); 55 scanf("%d%d%d",&n,&m,&num);n++; 56 S=2*n+1,T=S+1,SS=T+1,TT=SS+1; 57 for(int i=1;i<=n;i++)g[i][i]=0; 58 for(int i=1,u,v,w;i<=m;i++){ 59 scanf("%d%d%d",&u,&v,&w);u++;v++; 60 g[u][v]=g[v][u]=min(g[u][v],w); 61 } 62 for(int k=1;k<=n;k++) 63 for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) 64 if((k<=i||k<=j)&&g[i][j]>g[i][k]+g[k][j]) 65 g[i][j]=g[i][k]+g[k][j]; 66 for(int i=1;i<=n;i++){ 67 add(i,n+i,inf,0);add(n+i,T,inf,0); 68 add(i,TT,1,0);add(SS,n+i,1,0); 69 for(int j=i+1;j<=n;j++)add(n+i,j,inf,g[i][j]); 70 } 71 add(S,1,num,0);add(T,S,inf,0); 72 swap(S,SS),swap(T,TT); 73 printf("%d\n",work()); 74 return 0; 75 }