zoukankan      html  css  js  c++  java
  • 【u251】心灵的抚慰

    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;
    }
  • 相关阅读:
    提高C#编程水平的50个要点
    纯CSS Tooltips..
    分支结构程序设计
    个性测试题
    CSS与DIV
    数据库设计中的14个技巧
    XML文档处理(树的应用)
    使用设计模式构建通用数据库访问类
    什么样简历最受名企欢迎?
    如何做需求分析
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626940.html
Copyright © 2011-2022 走看看