zoukankan      html  css  js  c++  java
  • HDU 6386 Age of Moyu (最短路+set)

    <题目链接>

    题目大意:
    给定一张无向图,有n个点m条边,从一条边到另一条边,如果两边的指不同 花费就要+1,如果相同就不需要花费。 先从1走到n问最小花费是多少。(第一条边的花费都是1)

    解题分析:

    开始还以为类似于Dijkstra这样的贪心过程是伪的,但是本题确实是dijkstra,不过需要进行一些巧妙的变形,用一个set记录到达每个点的最优花费的所有的路径的前一条边(因为到达一个点的最优路径可能有多条),主要用于判断下一步花费是否需要+1。

    //set[u]表示当前的u距离最短时,u的前一条边所有种类
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e5+5 , M = 2e5+5;
    const int INF = 0x3f3f3f3f;
    #define REP(i,s,t) for(int i=s;i<=t;i++)
    int n,m;
    int vis[N];
    
    struct Edge{ int to,nxt,val; }e[M<<1];
    int cnt,head[N];
    set<int>s[N];
    
    inline void init(){
        cnt=0;
        for(int i=0;i<=n;i++)s[i].clear();
        memset(head,-1,sizeof(head));
    }
    inline void add(int u,int v,int w){
        e[++cnt]=(Edge){ v,head[u],w };head[u]=cnt;
    }
    
    struct Node{
        int loc,dist;
        bool operator < (const Node & tmp)const{
            return dist>tmp.dist;
        }
    }node[N];
    
    void Dij(){
        priority_queue<Node>q;
        REP(i,1,n){
            vis[i]=0,node[i].loc=i,node[i].dist=INF;
        }
        node[1].dist=0;
        q.push(node[1]);
        while(!q.empty()){
            int u=q.top().loc;q.pop();
            if(vis[u])continue;
            vis[u]=1;
            for(int i=head[u];~i;i=e[i].nxt){
                int v=e[i].to;
                int w;
                if(s[u].count(e[i].val))w=node[u].dist;
                else w=node[u].dist+1;
                if(node[v].dist>w){     
                    node[v].dist=w;
                    s[v].clear();       //因为v点的最优花费发生更新,所以这里需要清空
                    s[v].insert(e[i].val);
                    q.push(node[v]);
                }
                else if(node[v].dist==w){
                    s[v].insert(w);
                }
            }
        }
    }
    int main(){
        while(~scanf("%d%d",&n,&m)){
            init();
            REP(i,1,m){
                int u,v,w;scanf("%d%d%d",&u,&v,&w);
                add(u,v,w);add(v,u,w);
            }
            Dij();
            if(node[n].dist==INF)puts("-1");
            else printf("%d
    ",node[n].dist);
        }
    }
  • 相关阅读:
    uva 1606 极角扫描
    Codeforces Round #304 (Div. 2) 题解
    Codeforces Round #306 (Div. 2) 题解
    Codeforces Round #299 (Div. 2) 题解
    树链剖分专题
    bzoj 1036: [ZJOI2008]树的统计Count
    bzoj 1007: [HNOI2008]水平可见直线
    bzoj 1003: [ZJOI2006]物流运输trans
    Codeforces Round #301 (Div. 2) 题解
    bzoj 1026: [SCOI2009]windy数
  • 原文地址:https://www.cnblogs.com/00isok/p/10961436.html
Copyright © 2011-2022 走看看