1. 程式人生 > >route(2018.10.24)

route(2018.10.24)

name 解法 滿足 ops 所有 變化 printf namespace names

建出最短路圖之後\(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]);
}

route(2018.10.24)