• 最短路必经点(边)


    OJ题号:

    洛谷T7025(蛟川书院团队私有)

    题目大意:
    给定一个边正权的无向图 $G = (V,E) $
    求S到T的最短路径上必经的点(边)
    $|V|≤100000$,$|E|≤300000$

    思路:

    首先用两趟Dijkstra构造出$S$到$T$的最短路网(由所有的最短路组成的图)。
    再在新图中对于每个点i,DP出各个点到$S$和$T$的路径数$S1_i$和$S2_i$。
    设从$S$到$T$的路径总数为$sum$。
    则满足$S1_i*S2_i=sum$的结点即为所求的结点。
    本来用vector存会TLE,只有85或90分。将图的存储方式改成手动模拟链表以后即可AC。

      1 #include<queue>
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<functional>
      7 #include<ext/pb_ds/priority_queue.hpp>
      8 inline int getint() {
      9     register char ch;
     10     while(!isdigit(ch=getchar()));
     11     register int x=ch^'0';
     12     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     13     return x;
     14 }
     15 const int N=100001,M=300001,inf=0x7fffffff;
     16 int n,m,s,t;
     17 struct Edge {
     18     int to,w,next;
     19 };
     20 Edge e[M<<1];
     21 int e1[N]={0},e2[N]={0},sz=0;
     22 inline void add_edge(const int u,const int v,const int w) {
     23     e[sz+1]=(Edge){v,w,e1[u]},e1[u]=++sz;
     24     e[sz+1]=(Edge){u,w,e2[v]},e2[v]=++sz;
     25 }
     26 struct Vertex {
     27     int id,d,cnt;
     28     bool operator > (const Vertex &x) const {
     29         return d>x.d;
     30     }
     31 };
     32 bool v[N];
     33 int d1[N];
     34 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex>,__gnu_pbds::pairing_heap_tag> q1;
     35 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex>,__gnu_pbds::pairing_heap_tag>::point_iterator p1[N];
     36 inline void Dijkstra1() {
     37     memset(v,0,sizeof v);
     38     for(register int i=1;i<=n;i++) {
     39         p1[i]=q1.push((Vertex){i,d1[i]=(i==s)?0:inf,(i==s)?1:0});
     40     }
     41     for(register int i=1;i<=n;i++) {
     42         Vertex x=q1.top();
     43         for(register int j=e1[x.id];j;j=e[j].next) {
     44             Edge &y=e[j];
     45             if(v[y.to]) continue;
     46             if(x.d+y.w<p1[y.to]->d) {
     47                 q1.modify(p1[y.to],(Vertex){y.to,d1[y.to]=x.d+y.w,x.cnt});
     48             }
     49             else if(x.d+y.w==p1[y.to]->d) {
     50                 q1.modify(p1[y.to],(Vertex){y.to,d1[y.to]=x.d+y.w,p1[y.to]->cnt+x.cnt});
     51             }
     52         }
     53         v[x.id]=true;
     54         q1.modify(p1[x.id],(Vertex){x.id,inf,x.cnt});
     55     }
     56 }
     57 int d2[N];
     58 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex>,__gnu_pbds::pairing_heap_tag> q2;
     59 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex>,__gnu_pbds::pairing_heap_tag>::point_iterator p2[N];
     60 inline void Dijkstra2() {
     61     memset(v,0,sizeof v);
     62     for(register int i=1;i<=n;i++) {
     63         p2[i]=q2.push((Vertex){i,d2[i]=(i==t)?0:inf,(i==t)?1:0});
     64     }
     65     for(register int i=1;i<=n;i++) {
     66         Vertex x=q2.top();
     67         for(register int j=e2[x.id];j;j=e[j].next) {
     68             Edge &y=e[j];
     69             if(v[y.to]) continue;
     70             if(x.d+y.w<p2[y.to]->d) {
     71                 q2.modify(p2[y.to],(Vertex){y.to,d2[y.to]=x.d+y.w,x.cnt});
     72             }
     73             else if(x.d+y.w==p1[y.to]->d) {
     74                 q2.modify(p2[y.to],(Vertex){y.to,d2[y.to]=x.d+y.w,p2[y.to]->cnt+x.cnt});
     75             }
     76         }
     77         v[x.id]=true;
     78         q2.modify(p2[x.id],(Vertex){x.id,inf,x.cnt});
     79     }
     80 }
     81 struct Edge2 {
     82     int to,next;
     83 };
     84 std::queue<int> q;
     85 Edge2 small_e[M<<2];
     86 int small_sz=0;
     87 int small_e1[N];
     88 int s1[N]={0},in1[N]={0};
     89 inline void DP1() {
     90     q.push(s);
     91     s1[s]=1;
     92     while(!q.empty()) {
     93         int x=q.front();
     94         for(register int i=small_e1[x];i;i=small_e[i].next) {
     95             int &y=small_e[i].to;
     96             s1[y]+=s1[x];
     97             if(!--in1[y]) {
     98                 q.push(y);
     99             }
    100         }
    101         q.pop();
    102     }
    103 }
    104 int small_e2[N];
    105 int s2[N]={0},in2[N]={0};
    106 inline void DP2() {
    107     q.push(t);
    108     s2[t]=1;
    109     while(!q.empty()) {
    110         int x=q.front();
    111         for(register int i=small_e2[x];i;i=small_e[i].next) {
    112             int &y=small_e[i].to;
    113             s2[y]+=s2[x];
    114             if(!--in2[y]) {
    115                 q.push(y);
    116             }
    117         }
    118         q.pop();
    119     }
    120 }
    121 int small_v[M]={0};
    122 int ans[N]={0};
    123 int main() {
    124     n=getint(),m=getint(),s=getint(),t=getint();
    125     for(register int i=0;i<m;i++) {
    126         int x=getint(),y=getint(),v=getint();
    127         add_edge(x,y,v);
    128     }
    129     Dijkstra1();
    130     Dijkstra2();
    131     int len=d1[t];
    132     memset(v,0,sizeof v);
    133     for(register int i=1;i<=n;i++) {
    134         for(register int j=e1[i];j;j=e[j].next) {
    135             if(d1[i]+e[j].w+d2[e[j].to]==len) {
    136                 small_e[small_sz+1]=(Edge2){e[j].to,small_e1[i]},small_e1[i]=++small_sz;
    137                 in1[e[j].to]++;
    138                 small_e[small_sz+1]=(Edge2){i,small_e2[e[j].to]},small_e2[e[j].to]=++small_sz;
    139                 in2[i]++;
    140                 if(!v[i]) {
    141                     small_v[++small_v[0]]=i;
    142                     v[i]=true;
    143                 }
    144                 if(!v[e[j].to]) {
    145                     small_v[++small_v[0]]=e[j].to;
    146                     v[e[j].to]=true;
    147                 }
    148             }
    149         }
    150     }
    151     DP1();
    152     DP2();
    153     int sum=s1[t];
    154     for(register int i=1;i<=small_v[0];i++) {
    155         if(s1[small_v[i]]*s2[small_v[i]]==sum) {
    156             ans[++ans[0]]=small_v[i];
    157         }
    158     }
    159     std::sort(&ans[1],&ans[ans[0]+1]);
    160     printf("%d
    ",ans[0]);
    161     for(register int i=1;i<=ans[0];i++) {
    162         printf("%d ",ans[i]);
    163     }
    164     return 0;
    165 }
  • 相关阅读:
    python线程池 ThreadPoolExecutor 的用法
    charles基本配置
    爬取咪哩咪哩动漫视频
    超级鹰识别验证码
    selenium滑动验证
    subprocess模块
    ffmpeg常用命令
    Appium环境搭建(详细)
    appium下载安装及环境配置
    MIPS——无符号乘法
  • 原文地址:https://www.cnblogs.com/skylee03/p/7246607.html
Copyright © 2020-2023  润新知