POJ图论问题 ——Floyd算法汇集

学习Floyd算法中。。。。。。

Floyd  : 计算任意两节点间的最短距离,三重循环,效率较低!

POJ 1125   Stockbroker Grapevine                    http://poj.org/problem?id=1125

问题简述:一群股票经理人传递虚假消息,问从哪个人那里发出消息,可以使大家在最短的时间内都收到消息!

解法:先用floyd算法计算出每两个人之间传递消息的最短时间,然后,对每个人进行遍历,找出时间最短的哪个人!

问题的关键就是第i个人传递消息使所有人都能接受的时间,注意这个时间就是i个人发出消息,到最后一个人接受到消息的时间,不存在累加问题,这里我就陷入最短路的思维定势中;

当最后一个人接收到消息后其他所有人肯定已经接受到了!所以最后一个人接收到消息的时间就是第i个人传递消息花费的总时间!

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define max 0xfffffff
 6 #define N 105
 7 int p[N][N];
 8 int n;
 9 void Floyd()
10 {
11     int i,j,k;
12     for(k=1;k<=n;k++)
13         for(i=1;i<=n;i++)
14             for(j=1;j<=n;j++)
15                 if(p[i][j]>p[i][k]+p[k][j])
16                     p[i][j]=p[i][k]+p[k][j];
17 }
18 
19 int main()
20 {
21     int i,j;
22     while(scanf("%d",&n)!=EOF)
23     {
24         if(n==0)  break;
25         for(i=1;i<=n;i++)
26             for(j=1;j<=n;j++)
27                 p[i][j]=max;
28         int c;
29         for(i=1;i<=n;i++)
30         {
31             scanf("%d",&c);
32             if(c==0) continue;//这里第一次,晕晕的用了次break,WA了两次
33             while(c--)
34             {
35                 int a,b;
36                 scanf("%d%d",&a,&b);
37                 if(p[i][a]>b)
38                     p[i][a]=b;
39             }
40 
41         }
42         Floyd();
43         int min=max;
44         int person;
45         for(i=1;i<=n;i++)
46         {
47             int temp=-1;
48             for(j=1;j<=n;j++)
49             {
50                 if(i!=j&&p[i][j]>temp)//注意这里要加上i!=j,或者在前边初始化时处理;
51                 temp=p[i][j];
52             }
53             if(temp<min)
54             {
55                 min=temp;
56                 person=i;
57             }
58         }
59         if(min==max)
60             printf("disjoint\n");
61         else
62             printf("%d %d\n",person,min);
63     }
64     return 0;
65 }

 

 

计算任意原点与目的地路径(可包含众多边)的最小边;

POJ 3615 Cow Hurdles     http://poj.org/problem?id=3615

POJ牛多啊!又一群牛啊!大意: 从A地到B地,中间不知道要过什么东东(单词不认识);反正需要跳,问从A到B最小的(必要)跳跃高度;

和昨晚做前天做的那个两个青蛙(http://www.cnblogs.com/heat-man/archive/2013/03/18/2966615.html 中Frogger)一样啊!只不过这个题有多次提问所以,Dijkstra估计要超时了!

这时就体现了Floyd的强大啊!

View Code
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 #define N 305
 6 #define max 0xfffffff
 7 int p[N][N];
 8 int n,m,t;
 9 void Floyd()
10 {
11     int i,j,k;
12     for(k=1;k<=n;k++)
13         for(i=1;i<=n;i++)
14             for(j=1;j<=n;j++)
15             {
16                 if(p[i][j]>p[i][k]&&p[i][j]>p[k][j])
17                     p[i][j]=p[i][k]>p[k][j]?p[i][k]:p[k][j];
18             }
19 
20 }
21 
22 int main()
23 {
24     int i,j;
25     while(scanf("%d%d%d",&n,&m,&t)!=EOF)
26     {
27         for(i=1;i<=n;i++)
28             for(j=1;j<=n;j++)
29             {
30                 if(i==j)  p[i][j]=0;
31                 else p[i][j]=max;
32             }
33         int a,b,height;
34         for(i=1;i<=m;i++)
35         {
36             scanf("%d%d%d",&a,&b,&height);
37             if(p[a][b]>height)
38                 p[a][b]=height;
39         }
40         Floyd();
41         for(j=1;j<=t;j++)
42         {
43             int a,b;
44             scanf("%d%d",&a,&b);
45             if(p[a][b]==max)
46                 printf("-1\n");
47             else
48             printf("%d\n",p[a][b]);
49         }
50 
51     }
52     return 0;
53 }
54     

本题,是floyd的应用,根据题意修改了floyd循环内的东东,就ok了!

 

 

POJ 3264 Balance Lineup   http://poj.org/problem?id=3264

好吧!翘了英语听力写的这一题啊!还好题目是看懂了!估计是听不懂,呵呵!

刚开始时觉得,在Floyd中只要出现p[i][j]<p[i][k]+p[k][j]即可,测试结果不对;后来想通了,需要经过三层循环后,再次遍历一遍f[i][i]是否大于1;

初始值也不恰当,p[i][j]初始为了最大,最后修改为0;

(初始值根据题目的具体条件设置,如果求最小值,初始为最大,否则初始为最小,不然容易出现不易察觉的错误!)

View Code
 1 #include<iostream>
 2 #include<cstring>
 3 #include<string>
 4 #include<cstdio>
 5 #include<map>
 6 using namespace std;
 7 #define N 35
 8 #define max 0
 9 double  p[N][N];
10 map<string,int>money;
11 int n,m;
12 int flag;
13 int temp;
14 void Floyd()
15 {
16     int i,j,k;
17      for(k=1;k<=n;k++)
18         for(i=1;i<=n;i++)
19           for(j=1;j<=n;j++)
20           {
21               
22               if(p[i][j]<p[i][k]*p[k][j])
23               {
24                   p[i][j]=p[i][k]*p[k][j];
25                 
26               }
27               
28               
29           }
30 }
31 
32         
33 int main()
34 {
35     int i,j;
36     flag=1;
37     while(scanf("%d",&n)&&n)
38     {
39         money.clear();
40         for(i=1;i<=n;i++)
41             for(j=1;j<=n;j++)
42             {
43                 if(i==j)
44                     p[i][j]=1;
45                 else
46                 p[i][j]=max;
47             }
48         for(i=1;i<=n;i++)
49         {
50             string name;
51             cin>>name;
52             money[name]=i;
53         }
54         scanf("%d",&m);
55         for(i=1;i<=m;i++)
56         {
57             string s1,s2;
58             double fac;
59             cin>>s1;scanf("%lf",&fac);cin>>s2;
60             p[money[s1]][money[s2]]=fac;
61         }
62         
63         Floyd();
64         for(i=1;i<=n;i++)
65             if(p[i][i]>1) break;
66         if(i<=n)
67         printf("Case %d: Yes\n",flag++);
68         else
69             printf("Case %d: No\n",flag++);
70     }
71     return 0;
72 }

 

转载于:https://www.cnblogs.com/heat-man/archive/2013/03/20/2970610.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值