CQOI新年好

                                       CQOI新年好                                             

重庆城里有n个车站,m条双向公路连接其中的某些车站。每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他车站,但不同的路径需要花费的时间可能不同。在一条路径上花费的时间等于路径上所有公路需要的时间之和。
  佳佳的家在车站1,他有五个亲戚,分别住在车站a,b,c,d,e。过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。怎样走,才需要最少的时间?

输入格式:

第一行:n(n<=50,000),m(m<=100,000)为车站数目和公路的数目。
  第二行:a,b,c,d,e,为五个亲戚所在车站编号(1<a,b,c,d,e<=n)。
  以下m行,每行三个整数x,y,t(1<=x,y<=n,1<=t<=100),为公路连接的两个车站编号和时间。

输出格式:

  仅一行,包含一个整数T,为最少的总时间

样例输入:

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

样例输出:

21

数据范围:

50%的数据满足,n<=1000,m<=10000;
100%的数据满足,n<=50000,m<=100000;

时间限制:

1000

空间限制:

512000
基础算法:最短路加dfs深搜,我们搜出2,3,4,5,6所有全排列,对于每个亲戚和他自己都跑个单源最短路,最终按那个序列走一趟,比一下大小就可以AC了。

/*
6  6
2  3  4  5  6
1  2  8
2  3  3
3  4  4
4  5  5
5  6  2
1  6  7*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<new>
#include<queue>
#include<iostream>
using  namespace  std;
int  s[7];
int  dis[7][50001];
int  n;
int  m,u,v,w,ans=2e9;
bool  pg[50001];
int  flag[7];
int  ll[7];
int  ne[300001],fir[50001],val[300001],to[300001],tot;
void  add( int  u, int  v, int  w)
{
     to[++tot]=v;val[tot]=w;ne[tot]=fir[u];fir[u]=tot;
}
queue< int > q;
int  doit()
{
     int  lol=0;
     for ( int  i=1;i<=6;i++)
     {
         lol+=dis[ll[i]][s[ll[i+1]]];
     }
     ans=min(lol,ans);
}
void  dfs( int  x)
{
     if (x==6) doit();
     for ( int  i=2;i<=6;i++)
     {
         if (!flag[i])
         {
             flag[i]=1;
             ll[x+1]=i;
             dfs(x+1);
             flag[i]=0;
             ll[x+1]=0;
         }
     }
}
int  main()
{
     cin>>n>>m;
     s[1]=1;
     ll[1]=1;
     for ( int  i=2;i<=6;i++) cin>>s[i];
     for ( int  i=1;i<=m;i++)
     {
         cin>>u>>v>>w;
         add(u,v,w);
         add(v,u,w);
     }
     for ( int  i=1;i<=6;i++)
     {
         while (!q.empty())q.pop();
         for ( int  j=1;j<=n;j++) dis[i][j]=1e8;
         for ( int  j=1;j<=n;j++) pg[j]=0;
         q.push(s[i]);dis[i][s[i]]=0;pg[s[i]]=1;
         while (!q.empty())
         {
             int  xx=q.front();
             q.pop();pg[xx]=0;
             for ( int  k=fir[xx];k;k=ne[k])
             {
                 int  ttt=to[k];
                 if (dis[i][xx]+val[k]<=dis[i][ttt])
                 {
                     dis[i][ttt]=dis[i][xx]+val[k];
                     if (!pg[ttt])
                     {
                         q.push(ttt);
                         pg[ttt]=1;
                     }
                 }
             }
         }
     }
     dfs(1);
     cout<<ans;
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值