• 刷题总结———长跑路径(ssoj1982)


    题目:

      给定一个无向图···求特定几个点中两两间的最短路中的最小值····其中1≤N,M≤100000;T≤5;1≤K≤n;1≤边长≤100000,T为一个测试点的测试数··k为测试点数量

    题解:

      我们按1到k给每个点编一个编号······然后枚举编号的二进制的每一位,将这一位为1的点连边S(作为起点),为0的点连边T(作为终点),跑最短路就可以了···时间复杂度n*logn*logn···

      以后求最短路都用dijkstra不用SPFA了···注意当我们一求出连向T的点中第一个点的最小值时就可以break了····因为每个点每次入队时的距离就是其最小值··

      不得不说按二进制分类的方法很妙啊···

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<queue>
    using namespace std;
    priority_queue< pair<int,int> >que;
    const int N=1e5+5;
    int first[N],go[N*2],next[N*2],val[N*2],tot;
    int T,n,m,k,spep[N],num[N],ans,dis[N];
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())  f=(f<<3)+(f<<1)+c-'0';
      return f;
    }
    inline void pre()
    {
      memset(first,0,sizeof(first));tot=0;ans=0x3f3f3f3f;memset(num,0,sizeof(num));
    }
    inline void comb(int a,int b,int c)
    {
      next[++tot]=first[a],first[a]=tot,go[tot]=b,val[tot]=c;
      next[++tot]=first[b],first[b]=tot,go[tot]=a,val[tot]=c;
    }
    inline void getans()
    {
      for(int t=0;(1<<t)<=k;t++)
      {
        memset(dis,0x3f3f3f3f,sizeof(dis));
        while(!que.empty())  que.pop();
        for(int i=1;i<=k;i++)
          if(num[spep[i]]&(1<<t))  
            dis[spep[i]]=0,que.push(make_pair(0,spep[i]));   
        while(!que.empty())
        {
          int u=que.top().second;     
          que.pop();
          if(num[u]&&!(num[u]&(1<<t)))  {ans=min(ans,dis[u]);break;}
          for(int e=first[u];e;e=next[e])
          {
            int v=go[e];
            if(dis[v]>dis[u]+val[e]) 
            {
              dis[v]=dis[u]+val[e];
              que.push(make_pair(-dis[v],v));
            }
          }
        }
      }
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      T=R(); 
      while(T--)
      {
        pre();
        n=R(),m=R();int a,b,c;
        for(int i=1;i<=m;i++)  a=R(),b=R(),c=R(),comb(a,b,c);
        k=R();
        for(int i=1;i<=k;i++)  spep[i]=R(),num[spep[i]]=i;
        getans();cout<<ans<<endl;
      }  
      return 0;
    }
  • 相关阅读:
    泛型技巧系列:如何提供类型参数之间的转换
    一些支离破碎的泛型反射技巧
    泛型技巧系列:类型字典和Type Traits
    Excel开发:简化工作表中选定区域的操作。
    趣味程序:打印自己代码的程序
    VBF BETA 1.5 发布了
    .NET 2.0 CER学习笔记
    随笔乱入,开心就好
    Cocos2dx for WindowsPhone:开发一个打地鼠游戏(下)
    跨平台网络游戏趋势和优势
  • 原文地址:https://www.cnblogs.com/AseanA/p/7676757.html
Copyright © 2020-2023  润新知