zoukankan      html  css  js  c++  java
  • Cq OI 2005 新年好

    简要分析:

    1. 本题要求经过一定的点的最短路
    2. 易得,从 i 点出发,经过 k 点 ,到达 j 点的最短路, 一定是从 i 到 k 的最短路加上从 k 到 j 的最短路
      • 证明 :假设:从 i 点出发,经过 k 点 ,到达 j 点的最短路,不是从 i 到 k 的最短路加上从 k 到 j 的最短路
      • 则应存在 路径 E1(i->k)+E2(k->j)<E1min+E2min 易证得假设不成立
    3. 枚举 从每个亲戚家出发到达其它车站所需时间
    4. 再枚举每种路径所需时间
    5. 时间复杂度(5*M log M+5^5) 可以接受

    注意事项

    1. 本题是无向图,注意建图和建边
    2. 注意每次dijkstra都要重新预处理

    具体代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int inf=2147483637,Max_N=50010,Max_M=100010;
    typedef pair<int,int>node;
    struct Edge
    {
        int dis,to,next;
    } E[Max_M*2];//注意是无向边
    int Head[Max_N],Dis[6][Max_N],num_Edge,vis[Max_N];
    inline  int Read(void)//快读 
    {
        char ch=0;
        int w=0,x=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
        return w?-x:x;
    }
    inline void  Add_Edge(int from,int to,int dis)//建边 
    {
        E[++num_Edge].dis =dis;
        E[num_Edge].to =to;
        E[num_Edge].next =Head[from];
        Head[from]=num_Edge;
    }
    int N,M,T[6],S,Ans=inf;
    inline void Dijkstra(int num)//求从T[num]点出发到达每点的最短路 
    {
        priority_queue <node,vector<node>,greater<node> >Q;
        for(int i=1; i<=N; ++i) Dis[num][i]=(i==S?0:inf),vis[i]=0;
        Q.push(make_pair(0,S)) ;
        while(!Q.empty() )
        {
            int u=Q.top() .second;
            Q.pop() ;
            if(vis[u])continue;
            else vis[u]=1;
            for(int i=Head[u]; i; i=E[i].next )
            {
                int v=E[i].to ;
                if(Dis[num][v]>Dis[num][u]+E[i].dis )
                {
                    Dis[num][v]=Dis[num][u]+E[i].dis ;
                    if(!vis[v]) Q.push(make_pair(Dis[num][v],v)) ;
                }
            }
        }
    }
    int main(void)
    {
        N=Read(),M=Read();
        for(int i=1; i<=5; ++i) T[i]=Read();
        for(int i=1; i<=M; ++i)
        {
            int u=Read(),v=Read(),d=Read();
            Add_Edge(u,v,d);//注意是无向边
            Add_Edge(v,u,d);
        }
        T[0]=1;
        for(int i=0; i<=5; ++i)
        {
            S=T[i];
            Dijkstra(i);
        }
        memset(vis,0,sizeof(vis));
        for(int t1=1; t1<=5; ++t1)//枚举路径 
        {
            vis[t1]=1;
            for(int t2=1; t2<=5; ++t2)
            {
                if(!vis[t2])
                {
                    vis[t2]=1;
                    for(int t3=1; t3<=5; ++t3)
                    {
                        if(!vis[t3])
                        {
                            vis[t3]=1;
                            for(int t4=1; t4<=5; ++t4)
                            {
                                if(!vis[t4])
                                {
                                    vis[t4]=1;
                                    for(int t5=1; t5<=5; ++t5)
                                    {
                                        if(!vis[t5])
                                        {
                                            Ans=min(Ans,Dis[0][T[t1]]+Dis[t1][T[t2]]+Dis[t2][T[t3]]+Dis[t3][T[t4]]+Dis[t4][T[t5]]);
                                        }
                                    }
                                    vis[t4]=0;
                                }
                            }
                            vis[t3]=0;
                        }
                    }
                    vis[t2]=0;
                }
            }
            vis[t1]=0;
        }
        printf("%d
    ",Ans);
        return 0;
    }
  • 相关阅读:
    SQL 视图 局部变量 全局变量 条件语句 事务 触发器
    asp.net中的cookie
    Ajax 学习笔记
    接口与抽象类
    log4net日志组件
    StringBulider简单用法
    Web.Config文件详解
    性能优化之无阻塞加载脚步方法比较
    vue双向数据绑定原理探究(附demo)
    让你的JS更优雅的小技巧
  • 原文地址:https://www.cnblogs.com/Blacktears/p/11529151.html
Copyright © 2011-2022 走看看