zoukankan      html  css  js  c++  java
  • 计蒜客复赛 D.百度地图导航 最短路

    题目链接:

    https://nanti.jisuanke.com/t/15969

    题意:

    n个点,m个城市群,有两种边,第一种是正常的城市u与城市v之间的连边,第二种是城市群与群之间的连边,群与群之间的连边的意思是两个群之间任意两个点有一条边权为w的边。求s-t的最短路。

    思路:

    主要是如何处理群与群之间的连边,因为每个群最多可以2e4个点,暴力建边会T,所以我们把每个群抽象出两个点,一个点代表可以从它进入,一个点代表可以从它出去。群与群之间的边抽象成了有向边,因为这样就使得当本群里面的两个点没有边的时候,那么不能互相到达,当且仅当这个群和其他的群有第二种边,那么本群里两个点就可以相互到达,且距离是2*w,下面是官方题解:

    把每个城市群抽象成两个点 s', s"​​。按照如下方式见图:

    对于每个城市群里面的城市 si​​,连边:(si,s',0),(s",si,0)

    第一种边正常连边:(u, v, c), (v, u, c)

    第二种边连边:(a',b",l),(b',a",l)

    然后跑一遍 s-t 最短路就是答案。

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 2e4+10;
    17 
    18 int n,m;
    19 ll d[maxn*3];
    20 vector<pair<int,int> > g[3*maxn];
    21 
    22 int main(){
    23     scanf("%d%d",&n,&m);
    24     for(int i=1; i<=m; i++){
    25         int k = read();
    26         for(int j=1; j<=k; j++){
    27             int t = read();
    28             g[t].push_back(MP(n+i,0));
    29             g[n+m+i].push_back(MP(t,0));
    30         }
    31     }
    32     int m1,m2,u,v,w;
    33     m1 = read();
    34     for(int i=1; i<=m1; i++){
    35         scanf("%d%d%d",&u,&v,&w);
    36         g[u].push_back(MP(v,w));
    37         g[v].push_back(MP(u,w));
    38     }
    39     m2 = read(); int a,b;
    40     for(int i=1; i<=m2; i++){
    41         scanf("%d%d%d",&a,&b,&w);
    42         g[a+n].push_back(MP(b+m+n,w));
    43         g[b+n].push_back(MP(a+m+n,w));
    44     }
    45 
    46     int s,t; scanf("%d%d",&s,&t);
    47     for(int i=0; i<=n+2*m; i++) d[i] = INFLL;
    48 
    49     priority_queue<pair<ll,int> > Q;
    50     d[s]=0;
    51     Q.push(MP(-d[s],s));
    52     while(!Q.empty()){
    53         int now = Q.top().second;
    54         Q.pop();
    55         for(int i=0; i<(int)g[now].size(); i++){
    56             int v = g[now][i].first; ll w = g[now][i].second;
    57             if(d[now]+w < d[v]){
    58                 d[v] = d[now]+w;
    59                 Q.push(MP(-d[v],v));
    60             }
    61         }
    62     }
    63 
    64     if(d[t] == INFLL) puts("-1");
    65     else printf("%lld
    ",d[t]);
    66 
    67     return 0;
    68 }
  • 相关阅读:
    复制表部分内容到另一个表
    delphi使用ODAC控件TOraQuery操作表数据
    delphi使用ODAC控件查询存储过程返回结果集
    delphi使用ODAC控件事务处理(缓存提交)
    delphi使用ODAC控件事务处理(自动提交)
    delphi使用ODAC控件异步读取数据
    delphi使用ODAC控件常用功能
    delphi使用ODAC控件操作本地数据集
    时间限制关闭窗体的几点体会
    一个简单的双缓冲队列
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6979741.html
Copyright © 2011-2022 走看看