zoukankan      html  css  js  c++  java
  • dijkstra求最小环

    任意一个环的权值,我们都可以看成两个有边相连的结点i、j的直接距离加上i、j间不包含边(边i->j)的最短路径。

    求最短路径我们第一个想到的就是Dijkstra算法。

    而Dijkstra所求的是一个点到所有点的最短距离。

    用Dijkstra所求的i、j的最短距离一定是i、j的直接距离(如果i,j连通),所以我们需要先将i、j的边从图中删除(若i,j不连通,则不用删除),再用Dijkstra求新图中i、j的最短距离即可。

    所以我们每次在图中选取一条边,把它从图中删掉.

    然后对删掉的那条边所对应的2点进行Dijkstra,也就是m次Dijkstra。

    时间复杂度:若为稀疏图,复杂度为O(n^3)

                        若为稠密图,复杂度为O(n^4)

     

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<string>
     6 #include<queue>
     7 #include<cmath>
     8 #define ll long long
     9 #define DB double
    10 #define mod 1000000007
    11 #define eps 1e-3
    12 #define inf 2147483600
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,w=1;char ch=getchar();
    17     while(ch<'0' || ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    18     while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    19     return x*w;
    20 }
    21 const int N=1e3+90;
    22 struct node{
    23     int u,v,c,ne;
    24 }e[N];
    25 int h[N],tot,n,m,x,y;
    26 void add(int u,int v,int c)
    27 {
    28     tot++;e[tot]=(node){u,v,c,h[u]};h[u]=tot;
    29 }
    30 struct kk{
    31     int id,dis;
    32     bool operator<(const kk &x)const{
    33       return dis>x.dis;
    34     }
    35 };
    36 int d[N],v[N],ans;
    37 priority_queue<kk>q;
    38 void dijkstra(int s)
    39 {
    40     for(int i=1;i<=n;++i) d[i]=inf,v[i]=0;
    41     d[s]=0;q.push((kk){s,0});
    42     while(!q.empty())
    43     {
    44         int ff=q.top().id,dis=q.top().dis;q.pop();
    45         if(v[ff]) continue;
    46         v[ff]=1;
    47         for(int i=h[ff];i;i=e[i].ne)
    48         {
    49             int rr=e[i].v;
    50             if(ff==x && rr==y) continue;
    51             if(ff==y && rr==x) continue;
    52             d[rr]=dis+e[i].c;
    53             q.push((kk){rr,d[rr]});
    54         }
    55     }
    56 }
    57 int main()
    58 {
    59     while(scanf("%d%d",&n,&m)!=EOF)
    60     {
    61          tot=0;ans=inf;
    62          memset(h,0,sizeof(h));
    63          for(int i=1;i<=m;++i)
    64          {
    65             int x,y,c;x=read();y=read();c=read();
    66             add(x,y,c);add(y,x,c);
    67          }
    68           for(int i=1;i<=tot;i+=2)
    69           {
    70              x=e[i].u;y=e[i].v;
    71              dijkstra(x);
    72              ans=min(ans,d[y]+e[i].c);
    73           }
    74           if(ans==inf) cout<<"It's impossible."<<endl;
    75           else cout<<ans<<endl; 
    76     }
    77     return 0;
    78 }
    View Code

    大部分情况下还是不用这个的,因为会T很惨。

    喵喵~~

  • 相关阅读:
    只用一个字节 计算象棋将帅之间可能的位置
    后缀数组学习
    java 构造不可变类集的使用方法
    topcoder SRM 639 div2
    navicat和pymysql
    表查询
    表的关系对应
    MySQl数据类型和条件限制
    复习之网络编程
    协程
  • 原文地址:https://www.cnblogs.com/adelalove/p/8488185.html
Copyright © 2011-2022 走看看