floyd算法模板HDU1869and求最小环HDU1599

作用:求出图中任意两节点间的最短路径。

时间复杂度:o(n^3);

空间复杂度:o(n^2); mp[i][j]代表从i到j的最短路

算法思想:动态规划

      从i到j  经过k节点或者不经过k节点

      若经过k  则 mp[i][j]=mp[i][k]+mp[k][j];

      else     mp[i][j]保持不变

floyd的模板

void floyd()
{
    for(int k=0;k<n;k++)
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
}

  floyd算法的优点:简单好写

  缺点:空间时间复杂度太高,用邻接矩阵很好写,用链式前向星就不太好写了。

以下为HDU1869代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=105,INF=10000000;
 4 int mp[maxn][maxn];
 5 int n,m,a,b;
 6 void input()
 7 {
 8     for(int i=0;i<n;i++)
 9         for(int j=0;j<n;j++)
10             mp[i][j]=INF;
11 
12     while(m--)
13     {
14         cin>>a>>b;
15         mp[a][b]=mp[b][a]=1;
16     }
17 }
18 
19 void floyd()
20 {
21     for(int k=0;k<n;k++)
22         for(int i=0;i<n;i++)
23             for(int j=0;j<n;j++)
24                 mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
25 }
26 
27 int main()
28 {
29     while(cin>>n>>m)
30     {
31         bool flag = 0;
32         input();
33         floyd();
34         for(int i=0;i<n&&!flag;i++)
35             for(int j=0;j<n&&!flag;j++)
36                 if(mp[i][j]>7){
37                     cout<<"No"<<endl;
38                     flag=1;
39                     break;
40                 }
41         if(!flag) cout<<"Yes"<<endl;
42     }
43 
44 
45     return 0;
46 }
View Code

!! 求最小环

环 即从 i 点经过若干点后回到 i 点

经过   j  点和  k点  回到i点的方程是    dis[i][j]+mp[j][k]+mp[k][i];

以下是floyd求最小环的代码

void floyd()
{
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<k;i++)
            for(int j=i+1;j<k;j++)          //成环的序列一定有大小顺序 只要保证i j k 不同就行了
                minn=min(minn,dis[i][j]+mp[j][k]+mp[k][i]);//经过j和k点回到起点的最小值
        for(int i=1;i<=n;i++)              //普通floyd求两点最短路
            for(int j=1;j<=n;j++)               //在一个循环里  经过k点的dis被更新,下一个循环才会被求最小环使用
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    }
}
 1 /***
 2     *floyd求最小环
 3     *mi =min(mi,dis[i][j]+mp[j][k]+mp[k][i]);
 4     *mi 遍历所有边
 5 ******/
 6 #include <bits/stdc++.h>
 7 using namespace std;
 8 const int maxn = 105,INF=100000000;
 9 int n,m,a,b,c,minn,mp[maxn][maxn],dis[maxn][maxn];
10 
11 void input()
12 {
13     minn=INF;
14     for(int i=0;i<=n;i++)
15         for(int j=0;j<=n;j++)
16             mp[i][j]=dis[i][j]= INF;
17     while(m--)
18     {
19         scanf("%d%d%d",&a,&b,&c);
20         if(c<mp[a][b]){
21             mp[a][b]=mp[b][a]=dis[a][b]=dis[b][a]=c;
22         }
23     }
24 }
25 
26 void floyd()
27 {
28     for(int k=1;k<=n;k++)
29     {
30         for(int i=1;i<k;i++)
31             for(int j=i+1;j<k;j++)          //成环的序列一定有大小顺序 只要保证i j k 不同就行了
32                 minn=min(minn,dis[i][j]+mp[j][k]+mp[k][i]);//经过j和k点回到起点的最小值
33         for(int i=1;i<=n;i++)              //普通floyd求两点最短路
34             for(int j=1;j<=n;j++)               //在一个循环里  经过k点的dis被更新,下一个循环才会被求最小环使用
35                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
36     }
37 }
38 
39 int main()
40 {
41     while(cin>>n>>m)
42     {
43         input();
44         floyd();
45         if(minn==INF)cout<<"It's impossible."<<endl;
46         else cout<<minn<<endl;
47     }
48 }
View Code

 

posted @ 2017-04-03 22:01  小螺号打豆豆  阅读(147)  评论(0编辑  收藏  举报