(判断是否有1点或n点出发的环)
其他点的出入度相等,说明一定有一条1到n的路或者1自环和n自环
最终答案为1到n的最短路 or 1出发的自环+n出发的自环 中小的一个
// Decline is inevitable, romance will last forever.
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <cstdio>
using namespace std;
#define mst(a, x) memset(a, x, sizeof(a))
#define INF 0x3f3f3f3f
#define P 998244353
//#define int long long
const int maxn = 3e2 + 10;
const int maxm = 1e5 + 10;
int n, m, c;
struct Edge {
int to, dis, next;
}edge[maxm];
int head[maxn], dis[maxn], cnt;
bool vis[maxn];
struct node {
int dis;
int pos;
node(int _dis = 0, int _pos = 0) : dis(_dis), pos(_pos) {}
bool operator <(const node &x) const {
return dis > x.dis;
}
};
void add_edge(int u, int v, int w) {
cnt++;
edge[cnt].to = v;
edge[cnt].dis = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
priority_queue<node> q;
void dijkstra(int s) {
mst(vis, 0);
mst(dis, 0x3f);
//dis[s] = 0; 求最小环 不能将起点入队
//q.push(node(0, s));
for(int i = head[s]; i; i = edge[i].next) {
int y = edge[i].to;
int d = edge[i].dis;
if(y == s) //排除起点终点一样的边
continue;
dis[y] = d; //将所有与s点相连的边加入队列
q.push(node(d, y));
}
while(!q.empty()) {
node tmp = q.top();
q.pop();
int x = tmp.pos;
if(vis[x]) continue;
vis[x] = true;
for(int i = head[x]; i; i = edge[i].next) {
int y = edge[i].to;
if(dis[y] > dis[x] + edge[i].dis)
dis[y] = dis[x] + edge[i].dis,
q.push(node(dis[y], y));
}
}
}
void solve() {
while(scanf("%d", &n) != EOF) {
mst(head, 0);
cnt = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
int len;
scanf("%d", &len);
add_edge(i, j, len);
}
dijkstra(1);
int ans1 = dis[n]; //1到n的最短路
int ans2 = dis[1]; //1单独成环
dijkstra(n);
ans2 += dis[n]; //n单独成环
int ans = min(ans2, ans1);
printf("%d\n", ans);
}
}
signed main() {
// ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
// int T; scanf("%d", &T); while(T--)
// int T; cin >> T; while(T--)
solve();
return 0;
}