分析:
把所给矩阵当作邻接矩阵,由三个限制,可以得到:
1.节点 1 的出度为 1,但入度不确定;
2.节点 n 的入度为 1,但出度不确定;
3.其余节点的入度 = 出度;
当节点 1 的入度 =0,节点 n 的出度 =0,最小值就等于从 1→n的最短距离;
如果节点 1的入度 =1,节点 n 的出度 =1,那么节点 1,n 就都处在环中,求出两个最小环的距离和。二者取最小值。
求包含起点的最小环,不能先把起点入队,而先把起点连接的点入队,并把 dis[s] 赋 inf。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=310;
const ll inf=3e9+5;
int C[N][N];
ll dis[N];
int n;
bool vis[N];
queue<int>que;
void spfa(int s)
{
fill(vis+1,vis+1+n,false);
while(!que.empty())
que.pop();
for(int i=1;i<=n;i++)
{
if(i!=s)
{
que.push(i);
vis[i]=1;
dis[i]=C[s][i];
}
else
dis[s]=inf;
}
while(!que.empty())
{
int now=que.front();
que.pop();
vis[now]=0;
for(int i=1;i<=n;i++)
{
if(dis[i]>dis[now]+C[now][i])
{
dis[i]=dis[now]+C[now][i];
if(!vis[i])
{
vis[i]=1;
que.push(i);
}
}
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&C[i][j]);
spfa(1);
ll ans=dis[n];
ll res=dis[1];
spfa(n);
res+=dis[n];
printf("%lld\n",min(res,ans));
}
return 0;
}