• 选拔赛——旅游


      传送门

    题目大意:路上一共有三种风景点A,B,C,然后从1号点出发经过至少一个B和C类风景点,再回到1号点,然后问最短路径是多少?

    首先有3种风景点,因此对应就有8种状态(状态表示的是到某个点经过的风景点有哪些),到每个点都有8种状态,记录状态的话用的是dis数组的第二维(将第二维j转化为一个二进制数对应有3位,第一位表示的是A类风景点的状态,第二位表示的是B类风景点的状态,第三位表示的是C类风景点的状态,对应的数位若是1表示有经过,0表示没经过),定义dis[i][j]表示在j状态下到达i号点的最短路径,然后就用dij递推出dis[1][7]和dis[1][6](7表示的状态是111,6表示的状态是110,都是经过了B,C风景点的),挑个最小的即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn=200010;
    ll inf=1e15;
    struct node
    {
        int v;
        ll w;
        node(int vv=0,ll ww=0)
        {
            v=vv;
            w=ww;
        }
    };
    struct state
    {
        int v,sta;
        ll d;
        state(int vv=0,int staa=0,ll dd=0)
        {
            v=vv;
            sta=staa;
            d=dd;
        }
        friend bool operator <(const state&a,const state&b)
        {
            return a.d>b.d;
        }
    };
    vector<node>g[maxn];
    ll dis[maxn][10];//dis[i][j]表示j状态下到达i节点的最短路径
    int vis[maxn][10],val[maxn],n,m;
    void dij()
    {
        for(int i=1;i<=n;i++)
            for(int j=0;j<=8;j++)
                dis[i][j]=inf,vis[i][j]=0;
        dis[1][1<<val[1]]=0;
        priority_queue<state>q;
        while(!q.empty()) q.pop();
        q.push(state(1,1<<val[1],0));
        while(!q.empty())
        {
            state now=q.top();
            q.pop();
            int u=now.v,sta=now.sta;
            if(vis[u][sta]) continue;
            vis[u][sta]=1;
            for(int i=0;i<g[u].size();i++)
            {
                int v=g[u][i].v,nxtsta=sta|(1<<val[v]);
                ll w=g[u][i].w;
                if(!vis[v][nxtsta]&&dis[v][nxtsta]>(dis[u][sta]+w))
                {
                    dis[v][nxtsta]=dis[u][sta]+w;
                    q.push(state(v,nxtsta,dis[v][nxtsta]));
                }
    
    
            }
        }
    }
    
    int main()
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&val[i]);
        }
        while(m--)
        {
            int u,v;
            ll d;
            scanf("%d %d %lld",&u,&v,&d);
            g[u].push_back(node(v,d));
            g[v].push_back(node(u,d));
        }
        dij();
        printf("%lld
    ",min(dis[1][7],dis[1][6]));
        return 0;
    }
    
    

      

  • 相关阅读:
    jieba库分词统计
    第九次作业——测试报告和用户手册
    第八次作业——系统设计和任务分配
    第七次作业-团队选题报告和需求规格说明书
    第六次作业——结对项目之需求分析与原型设计
    小学四则运算的简单实现
    jieba库分词
    第九次团队作业——测试报告和用户手册
    第八次作业——系统设计与团队分配(个人)
    团队项目之选题报告和需求规格说明书
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754888.html
Copyright © 2020-2023  润新知