最短路必经点(边)

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\n",ans[0]);
161     for(register int i=1;i<=ans[0];i++) {
162         printf("%d ",ans[i]);
163     }
164     return 0;
165 }

 

posted @ 2017-07-27 19:03  skylee03  阅读(735)  评论(0编辑  收藏  举报