最短路必经点(边)
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 }