这个题说实话我没看出来,我看的别人的博客
https://blog.csdn.net/u013761036/article/details/39377499
这个人讲的很清楚,可以直接去看他的
题目给的 3个要求:
1.X 12+X 13+...X 1n=1
2.X 1n+X 2n+...X n-1n=1
3.for each i (1<i<n), satisfies ∑X ki (1<=k<=n)=∑X ij (1<=j<=n).
简单来说就是创建n个点,X 12+X 13+...X 1n=1 代表我们的 1点 的出度是1,这里没有对 1点 的入度做限制,也就是说入度可以为0
X 1n+X 2n+...X n-1n=1 代表 n点 的入读是n,同上,出度可以为0
for each i (1<i<n), satisfies ∑X ki (1<=k<=n)=∑X ij (1<=j<=n). 代表 2 到 (n-1) 这些点的入度等于出度
仔细想一下最短路,不也是这样吗,中间的点入度等于出度,初始点 入度为 0,结束的点出度为0
把 c这个矩阵看成任意两点间的距离,把 x 矩阵看成从1到n 最短路所要经过的路径,
求个最短路就是结果
当然还有一个特殊情况,就是 1到1的最小环+n到n的最小环,这样做出来也是满足那三个条件的
另外题目讲了c[i]>=0,不用担心负环
#include <iostream> #include <queue> #include <cstdio> #include <cmath> #include <cstring> using namespace std; int arr[305][305]; int n; bool vis[305]; int dis[305]; int spfa(int s,int e,int k) { memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int> q; if(k == 1) { q.push(s); vis[s] = true; dis[s] = 0; } else { for(int i = 1; i <= n; ++i) { if(i == s) continue; q.push(i); vis[i] = true; dis[i] = arr[s][i]; } } while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for(int i = 1; i <= n; ++i) { if(i == u) continue; if(dis[i]>dis[u] + arr[u][i]) { dis[i] = dis[u] + arr[u][i]; if(vis[i] == false) { vis[i] = true; q.push(i); } } } } return dis[e]; } int main() { while(scanf("%d",&n) != EOF) { for(int i = 1; i <= n; ++i) { for(int j = 1; j <= n; ++j) { scanf("%d",&arr[i][j]); } } int s1 = spfa(1,n,1); int s2 = spfa(1,1,2); int s3 = spfa(n,n,2); if(s1 > s2 + s3) s1 = s2 + s3; printf("%d\n",s1); } }