HDU

题意:N个点M条边的无向图,每条边都有属于自己的编号,如果一条路径上的边编号都相同,那么花费仅为1;改变至不同编号的路径,花费加1,无论这个编号之前是否走过。

分析:记录每个点的最小花费,再用set维护这个最小花费对应的前驱边的编号,可能有多个不同的前驱编号。如果当前状态可以更新点最小花费,那么将set清空并加入前驱编号;如果与最小花费相等且前驱的编号不在集合中,那么将前驱的状态加入集合中。

*BFS要用优先队列,否则会错。

#include<bits/stdc++.h>
using namespace std;
const int maxn =1e5+5;
const int INF = 0x3f3f3f3f;
struct Edge{
    int v,id,next;  
}edges[maxn<<2];
int head[maxn],tot;
int d[maxn];
set<int> sta[maxn];

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));    
}

void AddEdge(int u,int v,int id)
{
    edges[tot] = (Edge){v,id,head[u]};
    head[u] = tot++;
}

struct Node{
    int val,u;
    int pre,fa;
    bool operator <(const Node &p) const{return val>p.val;}
};
void BFS(int s,int t)
{
    memset(d,INF,sizeof(d));
    d[s] = 0;
    priority_queue<Node> Q;
    Q.push((Node){d[s],s,-1,-1});
    while(!Q.empty()){
        Node x=  Q.top();Q.pop();
        int pre = x.pre, u = x.u;
        if(x.val> d[u]) continue;
        else if(x.val==d[u]){
            bool tag = true;
            if(sta[u].find(pre)!=sta[u].end()) 
                continue;
            sta[u].insert(pre);
        }
        else{
            d[u] = x.val;
            sta[u].clear();
            sta[u].insert(pre);
        }

        for(int i=head[u];~i;i=edges[i].next){
            int v = edges[i].v,now = edges[i].id;
            if(v==x.fa) continue;                       //反向边
            if((d[u]+(pre!=now))<=d[v]){
                d[v] = d[u] + (pre!=now);
                if(v!=t) Q.push((Node){d[v],v,now,x.u});
            }
        }
    }
}

int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int N,M;
    int u,v,id;
    while(scanf("%d%d",&N,&M)==2){
        for(int i=1;i<=N;++i) sta[i].clear();
        init();
        while(M--){
            scanf("%d%d%d",&u,&v,&id);
            AddEdge(u,v,id);
            AddEdge(v,u,id);
        }
        BFS(1,N);
        if(d[N]==INF) d[N]=-1;
        printf("%d
",d[N]);
    }
    return 0;
}
为了更好的明天
原文地址:https://www.cnblogs.com/xiuwenli/p/9470019.html