打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
route(2018.10.24)

建出最短路图之后\(topsort\)即可。
具体思路:
先用\(dijkstra\)算法在原图中跑出\(1\)号点到\(i\)号节点的最短距离\(dist_1(i)\),将所有边反向后用\(dijkstra\)算法求出\(i\)号点到\(2\)号点的最短距离\(dist_2(i)\);
再沿着最短路径找到从\(1\)号点到\(i\)号点的方案数\(f(i)\),以及\(i\)号点到\(2\)号点的方案数\(g(i)\);
如果一条起点为\(a_i\),终点为\(b_i\),长度为\(c_i\)的边满足\(f(a_i)*g(b_i)==f(2)\)且\(dist_1(i) c_i dist_2(i)==dist_1(2)\)则该边是原图中从\(1\)号点到\(2\)号的最短路径的必经之路。
将第i条边反向后对该边进行分类讨论
\(1.dist_2(ai) dist_1(bi) ci < dist_1(2)\) 则最短路径的长度变短了
\(2.dist_2(ai) dist_1(bi) ci == dist_1(2)\) ,则最短路径的长度并没有发生变化
\(3.dist_2(ai) dist_1(bi) ci > dist_1(2)\)
\(a.\)如果该边不是原图最短路径的必经之路,则最短路径的长度并没有发生变化
\(b.\)如果该边是原图最短路径的必经之路,则最短路径的长度变长了或者新图中不存在从\(1\)号点到\(2\)号点的路径
(当不存在从\(1\)号点到\(i\)号点的路径时,\(dist_1(i)\)为极大值,\(dist_2(i)\)同理)
时间复杂度\(O((m n)log(n))\),但当路径数量过多时,\(f\)值和\(g\)值会超出\(int\)的储存范围
期望\(100\)分解法:
在上述求必经之路的时候用拓扑序或者其他方法求在最短路径构成的图上的桥
但是我太傻逼了,唉!

代码:

#include<cstdio>#include<queue>#include<cstring>using namespace std;int n,m,x[100001],y[100001],cnt,ans[100001],z[100001],dis[100001],dis1[100001],pre[100001],nxt[100001],h[100001],v[100001],c[100001],sum,in[100001],pree[100001],nxtt[100001],hh[100001],vv[100001],f[100001],g[100001];struct oo{int x,y;};bool vis[100001];bool operator<(oo a,oo b){return a.x>b.x;}priority_queue<oo>q;void add(int x,int y,int z){pre[  cnt]=y;nxt[cnt]=h[x];h[x]=cnt;v[cnt]=z;}void ins(int x,int y,int z){pree[  cnt]=y;nxtt[cnt]=hh[x];hh[x]=cnt;vv[cnt]=z;}void dijkstra(int x,int *dis,int id){    memset(vis,0,sizeof vis);    q.push((oo){0,x});dis[x]=0;    while(!q.empty())    {        oo x=q.top();q.pop();        if(vis[x.y])continue;vis[x.y]=1;        for(int i=h[x.y];i;i=nxt[i])            if(dis[pre[i]]>dis[x.y] v[i])            {                                                    dis[pre[i]]=dis[x.y] v[i];                q.push((oo){dis[pre[i]],pre[i]});            }    }}void topsort(int x,int *f){    queue<int>que;     que.push(x);f[x]=1;    while(!que.empty())    {        int now=que.front();que.pop();        for(int i=hh[now];i;i=nxtt[i])        {            f[pree[i]] =f[now];            if(!(--in[pree[i]]))que.push(pree[i]);        }    }}int main(){//  freopen("route.in","r",stdin);//  freopen("route.out","w",stdout);    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i  )scanf("%d%d%d",&x[i],&y[i],&z[i]),add(y[i],x[i],z[i]);    memset(dis1,63,sizeof dis1);memset(dis,63,sizeof dis);    dijkstra(2,dis1,0);    memset(h,0,sizeof h);cnt=0;    for(int i=1;i<=m;i  )add(x[i],y[i],z[i]);    dijkstra(1,dis,1);cnt=0;    memset(vis,0,sizeof vis);    for(int i=1;i<=n;i  )        for(int j=h[i];j;j=nxt[j])            if(dis[i] v[j] dis1[pre[j]]==dis[2])vis[j]=1,ins(i,pre[j],v[j]),x[cnt]=i,y[cnt]=pre[j],z[cnt]=v[j],in[pre[j]]  ;    topsort(1,f);    memset(hh,0,sizeof hh);memset(in,0,sizeof in);int sum=cnt;cnt=0;    for(int i=1;i<=sum;i  )ins(y[i],x[i],z[i]),in[x[i]]  ;    topsort(2,g);    for(int i=1;i<=n;i  )        for(int j=h[i];j;j=nxt[j])        {            if(vis[j]){if(f[i]*g[pre[j]]==f[2])ans[j]=1;}            else if(dis1[i] v[j] dis[pre[j]]<dis[2])ans[j]=-1;        }    for(int i=1;i<=m;i  )printf("%d\n",ans[i]);}
来源:http://www.icode9.com/content-4-67901.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
SPFA学习
ACM之路———算法模板(基础算法)
洛谷 P5905 【模板】Johnson 全源最短路
第三章 搜索与图论(一)
7-1 迷宫寻路 (20分)
SPFA 算法详解( 强大图解,不会都难!)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服