题目链接:点我啊╭(╯^╰)╮
夜已深、金庸先生走了、、感觉这是我们失去的时代…
题目大意:
给出一个
的矩阵
,要找出一个
的
矩阵
,使得
最小??
矩阵
满足下面几个条件:
- 对每个 , 满足
解题思路:
题目很诡异,如果不放在最短路的章节里,估计一般人想不到用最短路来做,我也是看了别人的思路才懂。。。
既然大家都喜欢看别人的思路的话,那我也来整理一下我的想法吧
既然是用最短路的思想来解决,那么我们首先就得找出虚拟出最短路的条件:点、边
首先,先虚拟出
个点,如果题目做多了话,可以想象这
个点和上面的矩阵相对应,那么接下来就是处理边的问题了,这里就需要抽象的理解题目给的三个条件:
- : 点 的出度为
- : 点 的入度为
- 对每个 , 满足 : 点 ~ 的入度和出度相同
如果能理解上面三个抽象的理解,那么转化为最短路也就更加容易抽象理解了,当然,如果你不能理解的话,emmm,那就多看几遍吧。。
点
的出度为
:即代表这张图由
出发
点
的入度为
:即代表这张图的终点为
点
~
的入度和出度相同:这张图中途可能经过点
~
,也就是一个完整的最短路了,从1跑到n求最短路径
当然,题目的精妙之处还在于,如果从点
出发,跑了一个圈(至少经过一个点)又回到了
,然后从
出发,跑了一个圈(至少经过一个点)又回到了
,会发现也是满足题意的,不信你可以对照要求
那么我们就还要求点
和点
的最小花费环,具体求法之间看代码就行了,答案为
代码思路:
用哪套最短路模板都行, 只有
核心:看似是数学题,实则是谁也想不到
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3F3F3F3F;
const int N = 1005;
int m, n, st, mp[N][N];
int dis[N], vis[N];
void creatgraph() {
int t1, t2, t3;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
scanf("%d", &mp[i][j]);
}
void dijkstra(int st) {
memset(vis, 0, sizeof(vis));
for (int i=1; i<=n; i++) dis[i] = mp[st][i];
dis[st] = INF;
for (int i=1; i<=n; i++) {
/*找出离起点最近的点*/
int minn = INF, k = -1;
for (int j=1; j<=n; j++) {
if (!vis[j] && dis[j]<minn) {
minn = dis[j];
k = j;
}
}
if(k==-1) break;
vis[k] = 1;
for (int j=1; j<=n; j++) { //松弛操作,找到媒介使得出现新的最短路
if (!vis[j] && dis[k]+mp[k][j] < dis[j])
dis[j] = dis[k] + mp[k][j];
}
}
}
int main() {
while(~scanf("%d", &n)) {
creatgraph(); //建图
dijkstra(1);
int ans = dis[n];
int loop1 = dis[1];
dijkstra(n);
int loop2 = dis[n];
ans = min(ans, loop1+loop2);
printf("%d\n", ans);
}
}