CJOI 2005 新年好

时间:2019-09-16
本文章向大家介绍CJOI 2005 新年好,主要包括CJOI 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\n",Ans);
    return 0;
}

原文地址:https://www.cnblogs.com/Blacktears/p/11529151.html