• POJ1135比较有意思的对短路(多米骨牌)


    题意:
         有一个骨牌游戏,就是推到一个后所有的牌都会被退到的那种游戏,起点是1,有两种骨牌,一种是关键牌,另一种是普通牌,普通牌是连接关键牌用的,给你一些边a b c的意思是关键牌a倒之后c时间b会被a的效应影响到,被推倒,然后问题是求出所有牌被都被推倒的时间,还有最后倒的牌处在的位置(两种情况,处在某一个关键牌上,处在某一条关键牌之间)。


    思路:
          可以用spfa或者是bfs啥的来做,我用的是spfa跑一遍最短路,跑完之后把所有到1节点的距离的最大的那个拿出来a,这个值有什么用?想下,假如最后倒下的骨牌是一个关键骨牌,那么是不是倒下的时间是这个值,到小的牌就是这个点,那么其他情况呢?也很好解决,我的想法是标记所有最短路上的边(不是单独一条路径,可以充当最短路上的边的边都行),那么这些边肯定可以再a时间内到达,其他的边就不一定了,所有枚举所有非最短路边,然后算出如果在当前路径上相遇的时间会是多少?边a b c 的话相遇时间是(dis[a]+dis[b]+c) / 2,如果比最短路的最长那个值还大,那么就更新最优,并且记录当前的这两个端点ab,如果所有的非最短路上的边,都没有更新值,也就是时间都比一开始那个最短的最长小,那么最后就是落在了唯一的一个特殊牌上了,具体细节可以看下下面代码。




    #include<queue>
    #include<stdio.h>
    #include<string.h>


    #define N_node 500 + 5
    #define N_edge 500000 + 100
    #define INF 1000000000


    using namespace std;


    typedef struct
    {
        int to ,next ,cost;
    }STAR;


    typedef struct
    {
        int a ,b ,c;
    }EDGE;


    STAR E[N_edge];
    EDGE edge[N_edge];
    int list[N_node] ,tot;
    int s_x[N_node] ,mark[N_node];


    void add(int a ,int b ,int c)
    {
        E[++tot].to = b;
        E[tot].cost = c;
        E[tot].next = list[a];
        list[a] = tot;
    }


    void Spfa(int s ,int n)
    {
        memset(mark ,0 ,sizeof(mark));
        for(int i = 0 ;i <= n ;i ++)
        s_x[i] = INF;
        queue<int>q;
        q.push(s);
        mark[s] = 1;
        s_x[s] = 0;
        while(!q.empty())
        {
            int xin ,tou;
            tou = q.front();
            q.pop();
            mark[tou] = 0;
            for(int k = list[tou] ;k ;k = E[k].next)
            {
                xin = E[k].to;
                if(s_x[xin] > s_x[tou] + E[k].cost)
                {
                    s_x[xin] = s_x[tou] + E[k].cost;
                    if(!mark[xin])
                    {
                        mark[xin] = 1;
                        q.push(xin);
                    }
                }
            }
        }
        return ;
    }


    int main ()
    {
        int n ,m ,a ,b ,c ,i;
        int cas = 1;
        while(~scanf("%d %d" ,&n ,&m) && n + m)
        {
            memset(list ,0 ,sizeof(list));
            tot = 1;
            for(i = 1 ;i <= m ;i ++)
            {
                scanf("%d %d %d" ,&a ,&b ,&c);
                add(a ,b ,c);
                add(b ,a ,c);
                edge[i].a = a;
                edge[i].b = b;
                edge[i].c = c;
            }
            printf("System #%d " ,cas ++);
            if(n == 1 && m == 0)
            {
                printf("The last domino falls after 0.0 seconds, at key domino 1. ");
                continue;


            }


            Spfa(1 ,n);
            double time = 0 ,maxt = 0;
            int maxid;
            for(i = 2 ;i <= n ;i ++)
            {
                if(maxt < s_x[i])
                {
                    maxt = s_x[i] * 1.0;
                    maxid = i;
                }
            }
            time = maxt;
            int aa = 0 ,bb = 0;
            for(i = 1 ;i <= m ;i ++)
            {
                a = edge[i].a ,b = edge[i].b ,c = edge[i].c;
                if(s_x[a] + c != s_x[b] && s_x[b] + c != s_x[a])
                {
                    double tmp = (s_x[a] + s_x[b] + c) / 2.0;
                    if(time < tmp)
                    {
                        time = tmp;
                        aa = a ,bb = b;
                    }
                }
            }


            printf("The last domino falls after %.1lf seconds, " ,time);
            a = aa < bb ? aa : bb;
            b = aa > bb ? aa : bb;
            if(maxt == time) printf("at key domino %d. " ,maxid);
            else printf("between key dominoes %d and %d. " ,a ,b);
        }
        return 0;
    }







  • 相关阅读:
    教你写能被舒服舒服又舒服地调用的iOS库
    无比迅速敏捷地开发iOS超精美控件
    iOS中UIlabel多行文本展示使用小结
    诸葛亮诫子书
    保留开阔的心灵空间
    iOS长按手势列表拖拽功能实现
    iOS通知使用小结
    真正的成熟
    生活的常态
    记一次LNMP 502问题的解决 (Nginx 、php、php-fpm)
  • 原文地址:https://www.cnblogs.com/csnd/p/12062522.html
Copyright © 2020-2023  润新知