1. 程式人生 > >Destination Unknown Gym

Destination Unknown Gym

  • 題意:n個點m條邊,s為起點,給一些終點,每一步只能走最短路問有哪些從起點到終點的最短路經過g,h
  • 思路:跑一邊起點s的最短路,再分別跑一邊以g,h為起點的最短路,然後判斷是否存在從s-t[i]經過g,h的最短路
  • 不能記錄路徑來判斷是因為可能有多條最短路會把g,h覆蓋。
  • #include<bits/stdc++.h>
    using namespace std;
    #define inf 0x3f3f3f3f
    #define maxn 52005
    bool vis[maxn];
    int n,m,t,s,g,head[maxn],pre[maxn],px,minn;
    int a,b,d,x[maxn],cnt,h,T,dis[5][maxn];
    vector<int>ans;
    struct node
    {
        int v,to,d;
    } edge[maxn*2];
    void add(int x,int y,int z)
    {
        edge[++cnt].v=y;
        edge[cnt].d=z;
        edge[cnt].to=head[x];
        head[x]=cnt;
    }
    struct edg
    {
        int ord,w;
        bool operator<(const edg&b)const
        {
            return w>b.w;
        }
    } top;
    void dij(int s,int ord)
    {
        priority_queue<edg>q;
        q.push(edg{s,0});
        dis[ord][s]=0;
        while(!q.empty())
        {
            top=q.top();
            q.pop();
            for(int i=head[top.ord]; i!=-1; i=edge[i].to)
            {
                int v=edge[i].v;
                int w=edge[i].d;
                if(dis[ord][v]>dis[ord][top.ord]+w)
                {
                    dis[ord][v]=dis[ord][top.ord]+w;
                    q.push(edg{v,dis[ord][v]});
                }
            }
        }
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            cnt=0;
            ans.clear();
            memset(dis,inf,sizeof(dis));
            memset(head,-1,sizeof(head));
            scanf("%d%d%d",&n,&m,&t);
            scanf("%d%d%d",&s,&g,&h);
            while(m--)
            {
                scanf("%d%d%d",&a,&b,&d);
                add(a,b,d);
                add(b,a,d);
            }
            dij(s,1);
            dij(h,3);
            dij(g,2);
            minn=dis[2][h];
            for(int i=0; i<t; i++)
            {
                scanf("%d",&x[i]);
                if(dis[1][x[i]]==dis[2][x[i]]+dis[1][h]+minn)
                    ans.push_back(x[i]);
                else if(dis[1][x[i]]==dis[3][x[i]]+dis[1][g]+minn)
                    ans.push_back(x[i]);
            }
            sort(ans.begin(),ans.end());
            int len=ans.size();
            for(int i=0; i<len; i++)
                if(i==len-1)printf("%d\n",ans[i]);
                else printf("%d ",ans[i]);
        }
        return 0;
    }