• POJ 3114 Tarjan+Dijkstra


    题意:
    间谍在战争期间想要传递一份谍报回国,谍报可以在邮局之间传递,但这种传递是单向的,并且会少耗一些时间。但是如果两个邮局在同一个国家的话,那么谍报在这两个邮局之间传递是不消耗时间的。如果几个邮局发出的谍报可以通过一些路径相互到达,那么这些邮局就属于一个国家。那么问题来了:给出一个起点和终点,问最快什么时候能够将谍报传递到。
    思路:
    先Tarjan缩点,然后跑Dijkstra(Floyd可能会被卡,但是貌似有个哥们【现在应该叫前辈了】多交了几次,卡1000ms过了)(也可以记忆化搜索,spfa什么的 看个人喜好吧…)
    原题请戳这里

    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int dfn[505],low[505],p[505],map[505][505],MAP[505][505],W[505],n,m,t,cnt;
    bool vis[505],VIS[505];
    vector<int>v[505];
    stack<int>stk;
    void tarjan(int x)
    {
        vis[x]=1;stk.push(x);low[x]=dfn[x]=++cnt;
        for(int i=0;i<v[x].size();i++)
            if(!dfn[v[x][i]])
                tarjan(v[x][i]),low[x]=min(low[x],low[v[x][i]]);
            else if(vis[v[x][i]])
                low[x]=min(low[x],dfn[v[x][i]]);
        if(low[x]==dfn[x]){
            t++;int jy;
            do jy=stk.top(),stk.pop(),p[jy]=t,vis[jy]=0;while(jy!=x);
        }
    }
    int dijkstra(int start,int end)
    {
        memset(VIS,0,sizeof(VIS));
        for(int i=1;i<=t;i++)
            W[i]=MAP[start][i];
        VIS[start]=1;
        for(int i=1;i<t;i++)
        {
            int minn=0x3fffffff,k=-1;
            for(int j=1;j<=t;j++)
                if(minn>W[j]&&!VIS[j])
                    minn=W[j],k=j;
            VIS[k]=1;
            for(int j=1;j<=t;j++)
                if(!VIS[j]&&W[j]>W[k]+MAP[k][j])
                W[j]=W[k]+MAP[k][j];
        }
        return W[end]<0x3ffffff?W[end]:-1;
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)&&n)
        {
            cnt=t=0;
            memset(map,0x3f,sizeof(map));
            memset(MAP,0x3f,sizeof(MAP));
            memset(dfn,0,sizeof(dfn));
            memset(vis,0,sizeof(vis));
            memset(p,0,sizeof(p));
            for(int i=1;i<=n;i++)v[i].clear();
            for(int i=1;i<=n;i++)map[i][i]=MAP[i][i]=0;
            for(int i=1;i<=m;i++)
            {
                register int xx,yy,weight;
                scanf("%d%d%d",&xx,&yy,&weight);
                v[xx].push_back(yy);
                if(weight<map[xx][yy])map[xx][yy]=weight;
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i])tarjan(i);
            for(int i=1;i<=n;i++)
                for(int j=0;j<v[i].size();j++)
                    if(p[i]!=p[v[i][j]])
                    MAP[p[i]][p[v[i][j]]]=min(MAP[p[i]][p[v[i][j]]],map[i][v[i][j]]);
            scanf("%d",&m);
            for(int i=1;i<=m;i++)
            {
                register int xx,yy;
                scanf("%d%d",&xx,&yy);
                if(p[xx]==p[yy])printf("0
    ");
                else
                {
                     int jy=dijkstra(p[xx],p[yy]);
                     if(jy==-1)printf("Nao e possivel entregar a carta
    ");
                     else printf("%d
    ",jy);
                }
            }
            printf("
    ");
        }
    }

    就是这位前辈,卡1000ms过的。。
    这里写图片描述
    Dijkstra还是快点儿的。
    这里写图片描述

  • 相关阅读:
    Pandas注意事项&窍门
    Pandas稀疏数据
    Pandas IO工具
    (bc 1002)hdu 6016 count the sheep
    (bc 1001) hdu 6015 skip the class
    hdu 1874 畅通工程续(迪杰斯特拉优先队列,floyd,spfa)
    克鲁斯卡尔(并查集)hdu 1233
    克鲁斯卡尔算法(最短路算法详解)
    最小生成树(普利姆算法、克鲁斯卡尔算法)
    pair 对组
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532483.html
Copyright © 2020-2023  润新知