• vijos 1046 floyd求最小环


    // 转自vijos题解

    最小环问题
    <1>朴素的算法:
    令e(u,v)表示u和v之间的连边,再令min(u,v)表示,删除u和v之间的连边之后,u和v之间的最短路
    最小环则是min(u,v) + e(u,v),时间复杂度是EV2。
    <2>改进的方法:
    在floyd的同时,顺便算出最小环
    g[i][j]=(i,j之间的边长)
    dist:=g;
    for k:=1 to n do
    begin
    for i:=1 to k-1 do
    for j:=i+1 to k-1 do
    answer:=min(answer,dist[i][j]+g[i][k]+g[k][j]);
    for i:=1 to n do
    for j:=1 to n do
    dist[i][j]:=min(dist[i][j],dist[i][k]+dist[k][j]);
    end;
    关于算法<2>的证明:
    一个环中的最大结点为k(编号最大),与他相连的两个点为i,j,这个环的最短长度为g[i][k]+g[k][j]+i到j的路径中,所有结点编号都小于k的最短路径长度
    根据floyd的原理,在最外层循环做了k-1次之后,dist[i][j]则代表了i到j的路径中,所有结点编号都小于k的最短路径
    综上所述,该算法一定能找到图中最小环。

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 99999999
    int e[105][105];
    int dist[105][105];
    int floyd(int n)
    {
    int minn=inf,i,j,k;
    for(k=1;k<=n;++k)
    {
    for(i=1;i<k;++i)
    for(j=1;j<i;++j)
    minn=min(minn,dist[i][j]+e[i][k]+e[k][j]);

    for(i=1;i<=n;++i)
    for(j=1;j<=n;++j)
    dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
    }
    return minn;
    }
    int main()
    {
    int n,m,i,j,k;
    while(cin>>n>>m){
    for(i=1;i<=n;++i)
    for(j=1;j<=n;++j)
    if(i==j) e[i][i]=dist[i][i]=0;
    else e[i][j]=dist[i][j]=inf;
    for(i=1;i<=m;++i){
    int a,b,c;
    cin>>a>>b>>c;
    //if(e[a][b]>c)
    e[a][b]=e[b][a]=c,
    dist[a][b]=dist[b][a]=c;

    }
    int w=floyd(n);
    if(w==inf)
    cout<<"No solution."<<endl;
    else cout<<w<<endl;
    }
    return 0;
    }

  • 相关阅读:
    nginx 平滑升级和location配置案例
    nginx
    基于zabbix的监控keepalive脑裂
    KVM部署
    基于keepalived的lvs负载均衡http集群
    高可用keepalived
    KVM
    无向图中 生成树,完全图,连通图 的区别
    java中 is
    第一章——软件工程学概述 思维导图
  • 原文地址:https://www.cnblogs.com/zzqc/p/6853068.html
Copyright © 2020-2023  润新知