以下摘自王哲凡教授的课件。
•
先构造出
S
到
T
的最短路网。
•
最短路网是啥?
•
满足
dis_(S,x)+W_(x,y)+dis_(y,T)=dis_(S,T)
的边
(
x,y
)
组成的图。
•
然后在最短路网上
dp
出
S
到每个点
x
的路径条数
P_x 和
每个点
x
到
T
的路径条数
Q_x
•
设
P_T=Q_S=Z
•
一个点
x
为必经点当且仅当
Z=P_x Q_x
•
一条边
(
x,y
)
为必经边当且仅当
Z=P_x Q_y
•
路径数太大爆
long
long
怎么办?
•
随便找个好看的数取模就好了嘛。
•
时间复杂度
O((n+m) logm)
大概
下面是我写的代码。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<bitset>
#include<queue>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define G getchar()
#define LL long long
#define pii pair<int,int>
#define mkp make_pair
#define X first
#define Y second
#define N 100005
#define NN 300005
#define inf=300000000
priority_queue<pii,vector<pii>,greater<pii> >pq;
int n,m,s,t;struct EDGE{int a,b,w;}e[NN];
int rhe[N],he[N],ne[NN<<1],to[NN<<1],W[NN<<1],tot;
int d[N],rd[N],md;bool vis[N];
int q[N],in[N],rin[N],f[N],rf[N],sum;
int ans[N],cnt;
void read(int &x){
char ch=G;
while(ch<48||ch>57)ch=G;
for(x=0;ch>47&&ch<58;ch=G)x=x*10+ch-48;
}
void add(int x,int y,int z){
to[++tot]=y;W[tot]=z;ne[tot]=he[x];he[x]=tot;
to[++tot]=x;W[tot]=z;ne[tot]=rhe[y];rhe[y]=tot;
}
void dijkstra(){
int i,x,y,tmp;
memset(d,63,sizeof d);
pq.push(mkp(d[s]=0,s));
while(!pq.empty()){
x=pq.top().Y;pq.pop();
if(vis[x])continue;vis[x]=1;
for(i=he[x];i;i=ne[i])
if((tmp=d[x]+W[i])<d[y=to[i]])
pq.push(mkp(d[y]=tmp,y));
}
md=d[t];
}
void rdijkstra(){
memset(vis,0,sizeof vis);
int i,x,y,tmp;
memset(rd,63,sizeof rd);
pq.push(mkp(rd[t]=0,t));
while(!pq.empty()){
x=pq.top().Y;pq.pop();
if(vis[x])continue;vis[x]=1;
for(i=rhe[x];i;i=ne[i])
if((tmp=rd[x]+W[i])<rd[y=to[i]])
pq.push(mkp(rd[y]=tmp,y));
}
}
void dp(){
int Ft=1,Rr=2,u,v,i;
for(f[q[1]=s]=1;Ft<Rr;){
for(i=he[u=q[Ft++]];i;i=ne[i]){
f[v=to[i]]+=f[u];
if(!(--in[v]))q[Rr++]=v;
}
}
sum=f[t];
}
void rdp(){
int Ft=1,Rr=2,u,v,i;
for(rf[q[1]=t]=1;Ft<Rr;){
for(i=rhe[u=q[Ft++]];i;i=ne[i]){
rf[v=to[i]]+=rf[u];
if(!(--rin[v]))q[Rr++]=v;
}
}
}
int main(){
int i;
read(n);read(m);read(s);read(t);
rep(i,1,m){
read(e[i].a);read(e[i].b);read(e[i].w);
add(e[i].a,e[i].b,e[i].w);
}
dijkstra();rdijkstra();
memset(he,0,sizeof he);memset(rhe,0,sizeof rhe);tot=0;
rep(i,1,m)if(d[e[i].a]+e[i].w+rd[e[i].b]==md)
add(e[i].a,e[i].b,e[i].w),++in[e[i].b],++rin[e[i].a];
dp();rdp();
rep(i,1,n)if(f[i]*rf[i]==sum)ans[++cnt]=i;
printf("%d\n",cnt);
sort(ans+1,ans+1+cnt);
rep(i,1,cnt)printf("%d ",ans[i]);puts("");
return 0;
}