版权声明:本文为博主原创文章,转载请附上源地址。 https://blog.csdn.net/Ema1997/article/details/79785521
最开始的时候,以为只要使第一行和第n列相应的X为1即可,后来看题解发现没有那么简单。其他的大大就把这道题当成了一道图论题来做。所输入的矩阵相当于一个邻接表矩阵,题目的条件的意思大概就是,1的出度为1,n的入度为1,其他点的出度和入度相等。而所要求的就是满足条件的路径的长度。而满足条件的路径有两种。
1.从1到n的路径
2.从1经过其他点形成的闭环与从n开始经过其他点所形成的闭环之和。
接下来就是很简单的实现了。我用的是SPFA,然后求闭环的时候,只用变化一点就好了。意思大概就是,求出源点到所有点的最短路后,将最短路加上这个点到源点的边,就形成了一个经过源点的闭环,而所有闭环中最短的那个,就是所要求的闭环。(和kuangbin大佬的方式不大一样,而且我觉得我自己的方法比较好理解一点,毕竟不用改SPFA。哈哈哈哈哈,这样说真的好掉人品啊。皮这一下很开心)
for (int i = 1; i <= n; i++) {
if (i == u) continue;
if (c > dis[i] + cost[i][u]) {
c = dis[i] + cost[i][u];
}
}
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 400;
int n;
int cost[maxn][maxn];
int dis1[maxn];
int dis2[maxn];
int vis[maxn];
int c1, c2;
void Init()
{
c1 = INF;
c2 = INF;
for (int i = 1; i <= n; i++) {
dis1[i] = INF;
dis2[i] = INF;
}
}
int SPFA(int u, int dis[])
{
memset (vis, 0, sizeof(vis));
int c = INF;
dis[u] = 0;
queue<int> q;
q.push(u);
vis[u] = 1;
while (!q.empty()) {
int t = q.front();
q.pop();
vis[t] = 0;
for (int i = 1; i <= n; i++) {
if (i == t) continue;
if (dis[i] > dis[t] + cost[t][i]) {
dis[i] = dis[t] + cost[t][i];
if (!vis[i]) {
q.push(i);
vis[i] = 1;
}
}
}
}
for (int i = 1; i <= n; i++) {
if (i == u) continue;
if (c > dis[i] + cost[i][u]) {
c = dis[i] + cost[i][u];
}
}
return c;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen ("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
while (scanf ("%d", &n) != EOF) {
Init ();
for (int i = 1; i<= n; i++) {
for (int j = 1; j <= n; j++) {
scanf ("%d", &cost[i][j]);
}
}
c1 = SPFA (1, dis1);
c2 = SPFA (n, dis2);
int c = c1 + c2;
if (c > dis1[n]) {
c = dis1[n];
}
printf ("%d\n", c);
}
}