• BZOJ 2200 道路与航线(缩点+最短路+拓扑排序)


    题目链接:https://www.acwing.com/problem/content/description/344/

    这道题看起来像用SPFA的单源最短路,但是经过了特殊处理,SPFA会被卡。

    所以就用到了缩点+拓扑最短路。

    道路是无向的,所以可以将整个图分成若干个连通块,然后将这些连通块缩成点,整体上跑拓扑,在跑拓扑的过程中,用堆优化的dijkstra来处理每一个连通块中的最短路。注意块与块之间的联系方式:对所有的都处理dis,然后处理dis完了之后再看与前一个节点是否是同一个连通块中的点。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<queue>
     4 #include<cstring>
     5 using namespace std;
     6 const int N=25005;
     7 const int INF=0x3f3f3f3f3f;
     8 queue<int> q;
     9 priority_queue<pair<int,int> > q1;
    10 int t,r,p,s;
    11 int cnt,tot;
    12 int head[N],c[N],vis[N],in[N],dis[N];
    13 struct node{
    14     int to,next,w;
    15 }edge[N*10];
    16 void add(int u,int v,int w){
    17     edge[tot].to=v;
    18     edge[tot].next=head[u];
    19     edge[tot].w=w;
    20     head[u]=tot++;
    21 }
    22 void DFS(int u){
    23     for(int i=head[u];i!=-1;i=edge[i].next){
    24         int v=edge[i].to;
    25         if(!c[v]){
    26             c[v]=c[u];
    27             DFS(v);
    28         }
    29     }
    30 }
    31 void toposort(){
    32     q.push(c[s]);
    33     dis[s]=0;
    34     for(int i=1;i<=cnt;i++){
    35         if(in[i]==0) q.push(i);
    36     }
    37     while(!q.empty()){
    38         int u=q.front(); q.pop();
    39         for(int i=1;i<=t;i++){
    40             if(c[i]==u) q1.push(make_pair(-dis[i],i));
    41         }
    42         while(!q1.empty()){
    43             int u=q1.top().second; q1.pop();
    44             if(vis[u]) continue;
    45             vis[u]=1;
    46             for(int i=head[u];i!=-1;i=edge[i].next){
    47                 int v=edge[i].to;
    48                 if(dis[u]+edge[i].w<dis[v]){
    49                     dis[v]=dis[u]+edge[i].w;
    50                     if(c[u]==c[v]) q1.push(make_pair(-dis[v],v));
    51                 }
    52                 if(c[u]!=c[v]&&--in[c[v]]==0) q.push(c[v]); 
    53             } 
    54         }
    55     }
    56 }
    57 int main(){
    58     memset(dis,0x7f,sizeof(dis));
    59     memset(head,-1,sizeof(head));
    60     scanf("%d%d%d%d",&t,&r,&p,&s);
    61     for(int i=1;i<=r;i++){
    62         int u,v,w;
    63         scanf("%d%d%d",&u,&v,&w);
    64         add(u,v,w); add(v,u,w);
    65     }
    66     for(int i=1;i<=t;i++){
    67         if(!c[i]){
    68             c[i]=++cnt;
    69             DFS(i);
    70         }
    71     }
    72     for(int i=1;i<=p;i++){
    73         int u,v,w;
    74         scanf("%d%d%d",&u,&v,&w);
    75         add(u,v,w);
    76         in[c[v]]++;
    77     }
    78     toposort();
    79     for(int i=1;i<=t;i++){
    80         if(dis[i]>INF) printf("NO PATH
    ");
    81         else printf("%d
    ",dis[i]);
    82     }
    83     return 0;
    84 }
    AC代码
  • 相关阅读:
    036 Python进阶小结
    035 异常处理
    033 数据类型分类
    034 Python深浅拷贝
    032 集合类型内置方法
    031 字典类型内置方法
    XML删除节点
    追加XML
    XML文档的读、写
    XML文档的创建
  • 原文地址:https://www.cnblogs.com/New-ljx/p/13922035.html
Copyright © 2020-2023  润新知