有向图最小环求解(水)

今天看到了一道在有向图上求解最小环的题目,于是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;
        }
    }
}
posted @ 2021-05-30 16:38  ZTer  阅读(752)  评论(0编辑  收藏  举报