链接
给定无向图,点数小于100,边数小于10000,要求最小环。 floyd可以直接做,O(n^3)可以接受。 转移就是d[i][j]+a[i][k]+a[k][j],d数组的含义就是普通的folyd,表示不经过k之后的节点,从i到j的最段路径 这样得到的就一定是一个环。
还有要求记录路劲,这是我觉得这题最值得我学习的地方之一。 用递归的方式,记录一个数组mid[i][j],表示如果从编号为k以下的点经过i到j可以找到路径,那么最短的路径的一个中间的节点是谁。 用这个数组,可以进行一个递归的方式来寻找中间经过的所有点。这个是可以证明的,如果这条路是i到j的最短路,那上面的所有点之间的最短路一定和这条路重合(很好证明,不说了) 这就是临界矩阵记录最短路路径的方法,单次查找是O(n)的,这题的n=100,总体是O(n^4),刚好通过。
额,还有一个挺重要的点,就是memset初始化数组为最大值,会把数组塞满,也就是,如果代码里面有运算是两个或者3个数字相加,没有排除这个最大值参加运算的可能性,那用long long+memset会爆long long。。。就很离谱,所以要注意。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <map>
#include <string.h>
#include <vector>
#define ll long long
using namespace std;
inline int read() {
char c=getchar();int a=0,b=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
ll n,m,a[101][101],d[101][101];
ll pos[101][101],ans;
vector<ll>path;
const int inf=0x3f3f3f3f;
void get_path(int x,int y)
{
if(pos[x][y]==0)return;
int mid=pos[x][y];
get_path(x,mid);
path.push_back(mid);
get_path(mid,y);
}
int main()
{