有向图最小环求解(水)
今天看到了一道在有向图上求解最小环的题目,于是yy出了这样一个算法。虽然因为种种原因没过,但是其正确性是可以保证的,所以整理一下。
对于一个有向图 \(G\) 来说,我们要求解其最小环,其实就是求出某一个点出发到达它自己的最短路径。
于是可以使用最短路算法,这里我们使用 dijkstra 来求解最短路,其核心思路就是在用初始节点更新它的所有子节点之后,重新把出发点的 dis 值赋值为 inf (无穷远),vis 设置为 0 (“未访问”),然后继续跑完整个最短路算法。此时我们求解出的就是包含当前节点的最小环。如果要求整张图的最小环,我们可以对每一个点使用一遍上述算法,求出每一个点的最小环,然后统计最小结果即可。
但是呢,这个算法求出的最小环可能是一个 2 元环,也就是类似于 1->2->1 这种环,同样的,对于无向图来说,它也不能求出 3 元环(因为每个点的子节点可以沿着当前边再走回原来节点)。
总复杂度\(O(n(n+m)logn)\)
伪代码:
struct Point{
int number,distance;
bool friend operator < (const Point a,const Point b){
return a.distance>b.distance;
}
};
struct Edge{
int to,cost;
};
std::vector<Edge>v[maxn];
std::priority_queue<Point>Queue;
int n,flag,ans=0x3f3f3f3f;
int distance[maxn],visit[maxn];
void dijkstra(int x){
flag=1;
memset(distance,0x3f,sizeof distance);
memset(visit,0,sizeof visit);
distance[x]=0;
Queue.push((Point){x,distance[x]});
while(Queue.size()){
x=Queue.top().number;
Queue.pop();
if(visit[x])
continue;
visit[x]=1;
for(int i=0;i<v[x].size();i++){
int y=v[x][i].to,z=v[x][i].size();
if(distance[y]>distance[x]+z){
distance[y]=distance[x]+z;
Queue.push((Point){y,distance[y]});
}
}
if(flag){
visit[x]=0;
distance[x]=0x3f3f3f3f;
flag=0;
}
}
}
繁华尽处,
寻一静谧山谷,
筑一木制小屋,
砌一青石小路,
与你晨钟暮鼓,
安之若素。