• poj3268 Silver Cow Party(农场派对)


    题目描述

    原题来自:USACO 2007 Feb. Silver

    N(1≤N≤1000)N (1 le N le 1000)N(1N1000) 头牛要去参加一场在编号为 x(1≤x≤N)x(1 le x le N)x(1xN) 的牛的农场举行的派对。有 M(1≤M≤100000)M(1le M le 100000)M(1M100000) 条有向道路,每条路长 Ti(1≤Ti≤100)T_i(1 le T_i le 100)Ti​​(1Ti​​100);每头牛都必须参加完派对后回到家,每头牛都会选择最短路径。求这 NNN 头牛的最短路径(一个来回)中最长的一条的长度。 特别提醒:可能有权值不同的重边。

    输入格式

    第 111 行:333 个空格分开的整数 N,M,XN,M,XN,M,X;

    第 2…M+12 ldots M+12M+1 行:333 个空格分开的整数 Ai,Bi,TiA_i, B_i, T_iAi​​,Bi​​,Ti​​,表示有一条从 AiA_iAi​​ 到 BiB_iBi​​ 的路,长度为 TiT_iTi​​。

    输出格式

    一行一个数,表示最长最短路的长度。

    样例

    样例输入

    4 8 2
    1 2 4
    1 3 2
    1 4 7
    2 1 1
    2 3 5
    3 1 2
    3 4 4
    4 2 3

    样例输出

    10

    翻译题目,我们需要知道关于一个点,它到所有点的最短路以及所有点到它的最短路。
    前者是最短路模板,后者是将所有边反着连,跑一边模板。
    至于用Dijkstra还是SPFA,一看,没有负权边,向上看,我叫什么?
    好了,用Dijkstra。
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #define in(a) a=read()
    #define REP(i,k,n)  for(int i=k;i<=n;i++)
    #define MAXN 100010
    using namespace std;
    inline int read(){
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar())
            if(ch=='-')
                f=-1;
        for(;isdigit(ch);ch=getchar())
            x=x*10+ch-'0';
        return x*f;
    }
    int n,m,s,ans=-2147483647;
    int total1,head1[MAXN],to1[MAXN],nxt1[MAXN],val1[MAXN];
    int total2,head2[MAXN],to2[MAXN],nxt2[MAXN],val2[MAXN];
    int dis1[MAXN],vis1[MAXN]; 
    int dis2[MAXN],vis2[MAXN];
    struct node{
        int a,b;
    };
    priority_queue<node> Q;
    bool operator < (node x,node y){
        return x.b > y.b;
    }
    inline void adl1(int a,int b,int c){
        total1++;
        to1[total1]=b;
        val1[total1]=c;
        nxt1[total1]=head1[a];
        head1[a]=total1;
        return ;
    }
    inline void adl2(int a,int b,int c){
        total2++;
        to2[total2]=b;
        val2[total2]=c;
        nxt2[total2]=head2[a];
        head2[a]=total2;
        return ;
    }
    void dijkstra1(){
        dis1[s]=0;
        Q.push(node{s,0});
        while(!Q.empty()){
            int u=Q.top().a;
            Q.pop();
            if(vis1[u])  continue;
            vis1[u]=1;
            for(int e=head1[u];e;e=nxt1[e])
                if(dis1[to1[e]]>dis1[u]+val1[e]){
                    dis1[to1[e]]=dis1[u]+val1[e];
                    Q.push(node{to1[e],dis1[to1[e]]});
                }
        }
        return ;
    }
    void dijkstra2(){
        dis2[s]=0;
        Q.push(node{s,0});
        while(!Q.empty()){
            int u=Q.top().a;
            Q.pop();
            if(vis2[u])  continue;
            vis2[u]=1;
            for(int e=head2[u];e;e=nxt2[e])
                if(dis2[to2[e]]>dis2[u]+val2[e]){
                    dis2[to2[e]]=dis2[u]+val2[e];
                    Q.push(node{to2[e],dis2[to2[e]]});
                }
        }
        return ;
    }
    int main(){
        in(n),in(m),in(s);
        int a,b,c;
        REP(i,1,m)  in(a),in(b),in(c),adl1(a,b,c),adl2(b,a,c);
        REP(i,1,n)  dis1[i]=dis2[i]=2147483647;
        dijkstra1();
        dijkstra2();
        REP(i,1,n)  ans=max(ans,dis1[i]+dis2[i]);
        cout<<ans; 
    }
     
  • 相关阅读:
    C语言初学 使用while语句统计输入字符个数
    C语言初学 比较五个整数并输出最大值和最小值2
    C语言初学 比较五个整数并输出最大值和最小值1
    C语言初学 计算表达式的值 switch的意义
    C语言初学 if-else语句判别在ASCII值中小于32的可控制符的类型
    C语言初学 if-else语句判断俩数的最大值
    C语言初学 计算二元一次方程的问题
    C语言初学 判断闰年的问题
    简单Elixir游戏服务器开篇
    关于Elixir游戏服设计系列
  • 原文地址:https://www.cnblogs.com/jason2003/p/9836631.html
Copyright © 2020-2023  润新知