NOIP模拟——规避(最短路计数)

传送门

考场想到了的,但是细节挂了

woj上lj数据跑spfa都可以过。。。。

注意在最短路计数的时候必须记visit,否则会重复访问一条边

dijkstra最短路也最好记一个(否则复杂度是错的)

主要是方案是一条边左右乘起来的平方(进去出去都要乘,两个人)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mk make_pair
inline int read(){
    char ch=getchar();
    int res=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}
const int N=100005;
const int M=400005;
const ll mod=1000000007;
int adj[N],nxt[M],str,des,to[M],n,m,cnt;
bool vis[N];
ll num[2][N],val[M],dis[2][N],maxn,ans;
inline void addedge(int u,int v,int w){
    nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
    nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,val[cnt]=w;
}
struct edge{
    int u,v;
        ll w;
}e[N<<1];
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
void spfa(int fir,int k)
{
    memset(vis,0,sizeof(vis));
    int x,y,i;num[k][fir]=1;
            dis[k][fir]=0;q.push(make_pair(0,fir));
    while(!q.empty())
    {
        x=q.top().second;q.pop();
        if(vis[x])continue;vis[x]=true;
        for(i=adj[x];i;i=nxt[i])
        {
            y=to[i];
            if(dis[k][y]>dis[k][x]+val[i])
            {
                num[k][y]=num[k][x];
                dis[k][y]=dis[k][x]+val[i];
                q.push(make_pair(dis[k][y],y));
            }
            else  if(dis[k][y]==dis[k][x]+val[i])
              num[k][y]=(num[k][y]+num[k][x])%mod;
        }
    }
}
int main(){
//    freopen("lx.cpp","r",stdin);
    n=read(),m=read();
    str=read(),des=read();
    for(int i=1;i<=m;++i){
        int u=read(),v=read(),w=read();
        e[i].u=u,e[i].v=v,e[i].w=w;
        addedge(u,v,w);
    }
    memset(dis,127,sizeof(dis));
    spfa(str,0);
    spfa(des,1);
    maxn=dis[0][des];
    for(int i=1;i<=m;++i){
        if((dis[0][e[i].u]+dis[1][e[i].v]+e[i].w)==maxn){
            if(abs(dis[0][e[i].u]-dis[1][e[i].v])<e[i].w){
                ans+=(num[0][e[i].u]*num[1][e[i].v])%mod*(num[0][e[i].u]*num[1][e[i].v])%mod,ans%=mod;
            }
        }
        if((dis[1][e[i].u]+dis[0][e[i].v]+e[i].w)==maxn){
            if(abs(dis[1][e[i].u]-dis[0][e[i].v])<e[i].w){
                ans+=(num[0][e[i].v]*num[1][e[i].u])%mod*(num[0][e[i].v]*num[1][e[i].u])%mod,ans%=mod;
            }
        }
    }
    for(int i=1;i<=n;++i){
        if((dis[0][i]+dis[1][i])==maxn){
            if(dis[0][i]==dis[1][i]){
                ans+=(num[0][i]*num[1][i])%mod*(num[0][i]*num[1][i])%mod,ans%=mod;
            }
        }
    }
    cout<<(((num[0][des]*num[1][str])%mod-ans+mod)%mod)<<'\n';
}

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/83754193