Time Limit: 1 second

Memory Limit: 128 MB

【问题描述】

病毒问题解决后,神牛们的心灵久久不能平静。他可以从一个程序联想到一些相似的程序。比如从程序1联想到2,从2联想到4,从4联想到6,从6联想到9……就像搜索一样一步一步越陷越深。不过同一种联想他只会联想一次。比如1、2之间他进行了一次联想,那么他不会再重新联想1到2,或2到1。如果他刚开始时想到的程序能够经过联想若干次后联想回到原程序,那不就乱回来了吗?由于神牛马上就要开乱,请在1秒内告诉他,他需要想哪个程序,以便乱回来。 给出一些程序和他们互相联想的关系(如果两个程序A、B有联系,神牛可以从A联想到B,也可以从B联想到A,但A、B之间神牛最多联想一次),请告诉神牛他需要想哪个程序,以便在最短的时间内乱回来,并输出这个最短时间。

【输入格式】

第一行有两个正整数N,M,分别表示程序个数和有多少对程序可以被神牛直接互相联想。 以下M行,每行三个正整数,分别表示一种联想的两端的程序的编号(从1开始),以及进行这种联想所需要的最短时间(≤3500)。

【输出格式】

如果神牛无论如何都再也乱不回来了,输出“He will never come back.”。 如果神牛能够乱回来,请输出神牛会乱多长时间。

【数据规模】

对于100% 的数据,n≤250。

Sample Input1

4 3

1 2 10

1 3 20

1 4 30

Sample Output1

He will never come back.

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=u251

【题解】


for (int k = 1;k <= n;k++)
{
for (int i = 1;i <= k-1;i++)
for (int j = i+1;j <= k-1;j++)
mi = min(mi,dis[i][j]+w[j][k]+w[k][i]);
for (int i = 1;i <= n;i++)
for (int j = 1;j <= n;j++)
dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
}

mi即为最小环

最小环是基于floyd算法实现的;

因为当k层循环进行到第k层时,任意两点之间通过中间节点1..k-1得到的最短路已经求出来了;

则我们枚举包含节点k的最小环(且除了k号节点外这个环里的其他节点编号都小于k),即dis[i][j(i到j的最短路,注意i到j的最短路不会包括k),然后加上w[j][k]+w[k][i];这样就是一个环形了;然后取最小值,那么就能搞出最小环了;

这里的w数组之所以要另用一个数组是因为如果直接写dis[j][k]+dis[k][i];那么你不能预测j到k的路径或k到i的路径里面会不会包含dis[i][j]中经过的点;如果有这种情况那么就不能称之为环了;

还有就是

        for (int i = 1;i <= k-1;i++)
for (int j = i+1;j <= k-1;j++)
mi = min(mi,dis[i][j]+w[j][k]+w[k][i]);

这里的j层循环必须从i+1开始,不然会出现两个节点直接走过去然后又直接走回来的情况(而题目不允许这样);(题目所给的边是无向边);



【完整代码】

#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#define LL long long using namespace std; const LL INF = 1e15;
const int MAXN = 300; int n,m;
LL w[MAXN][MAXN],dis[MAXN][MAXN]; int main()
{
//freopen("F:\\rush.txt","r",stdin);
for (int i = 0;i <= 250;i++)
for (int j = 0;j <= 250;j++)
w[i][j]=dis[i][j] = INF;
cin >>n >> m;
for (int i = 1;i <= m;i++)
{
int x,y;LL z;
cin >> x >> y >> z;
w[x][y] = z;
w[y][x] = z;
dis[x][y] = z;
dis[y][x] = z;
}
LL ans = INF;
for (int k = 1;k <= n;k++)
{
for (int i = 1;i <= k-1;i++)
for (int j = i+1;j <= k-1;j++)
ans = min(ans,dis[i][j]+w[j][k]+w[k][i]);
for (int i = 1;i <= n;i++)
for (int j = 1;j <= n;j++)
dis[i][j] = min (dis[i][j],dis[i][k]+dis[k][j]);
}
if (ans >= INF)
puts("He will never come back.");
else
cout << ans <<endl;
return 0;
}

最新文章

  1. Android零散
  2. AT指令获取基站信息
  3. notepad++插件
  4. zookeeper适用场景:如何竞选Master及代码实现
  5. Anchor和Dock的区别
  6. DBCP连接池原理分析及配置用法
  7. Delphi 在使用exports中的方法 带参数的用法
  8. 一种基于Qt的可伸缩的全异步C/S架构server实现(一) 综述
  9. [Ext.Net]GridPanel之Access数据库分页显示
  10. RPM安装gcc gcc-c++扩展
  11. VS2010查看源码对应的汇编语言
  12. Arthur and Walls CodeForces - 525D (bfs)
  13. 剑指offer 5.栈和队列 用两个栈实现队列
  14. SpringBoot之Swagger2
  15. python中os.path 与sys.path
  16. PHP5.4.0新特性研究
  17. Django(十一)请求生命周期之CBV与FBV
  18. python3 xml模块
  19. 开发一个微信小程序实例教程
  20. Ubuntu下搭建高匿HTTP代理(亲测可用)

热门文章

  1. 【Codeforces Round #428 (Div. 2) A】Arya and Bran
  2. JS实践与写博客-序
  3. web.xml的配置及加载顺序
  4. linux下加入用户并赋予root权限
  5. C# 反射具体解释
  6. @转EXT2-&gt;EXT3-&gt;EXT4
  7. LayoutAnimation-容器动画
  8. item-设置可见性
  9. 105.UDP通信实现广播
  10. Mongodb总结5-通过装饰模式,用Mongodb解决Hbase的不稳定问题