zoukankan      html  css  js  c++  java
  • 最短路必经点(边)

    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 }
  • 相关阅读:
    97. Interleaving String
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    94. Binary Tree Inorder Traversal
    odoo many2many字段 指定打开的form视图
    docker sentry 配置文件位置
    postgres 计算时差
    postgres 字符操作补位,字符切割
    postgres判断字符串是否为时间,数字
    odoo fields_view_get
  • 原文地址:https://www.cnblogs.com/skylee03/p/7246607.html
Copyright © 2011-2022 走看看