• 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
    ",ans[i]);
    }
    
  • 相关阅读:
    git中Please enter a commit message to explain why this merge is necessary.
    用$(this)选择其下带有class的子元素
    将某页面中ajax中获取到的信息放置到sessionStorage中保存,并在其他页面调用这些数据。
    返回顶部黑科技
    对于div里面内容过大根据长度或者宽度进行适配,然后可以滚轮缩放的功能
    vue runtime报错问题
    webpack简单配置
    input type=color 设置颜色
    vue统一注册组件
    vue模板字符串写法
  • 原文地址:https://www.cnblogs.com/lcxer/p/9845884.html
Copyright © 2020-2023  润新知