zoukankan      html  css  js  c++  java
  • Poj(2679),SPFA,二级比较

    题目链接:http://poj.org/problem?id=2679

    嗯,思路清晰,先DFS看是不是通路,接着就是SPFA找最短路(路是费用,费用相同就比较路的长度)。

    超哥的代码还有一点问题,初始化最小费用为0,也能AC,我不信,if语句也好像写错了,只能说明这个题目数据水。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    #define MAXN 1105
    #define MAXM 5005
    #define INF 0x3f3f3f3f
    
    struct Edge
    {
        int v,len,fee,next;
        Edge() {}
        Edge(int vv,int ll,int ff, int nn):v(vv),len(ll),fee(ff),next(nn) {}
    } e[2*MAXM];
    
    int n,m;
    int dept,dest;
    int h[MAXN], le;
    int minfee[MAXN], minFee[MAXN];
    int vis[MAXN];
    int d[MAXN], cnt[MAXN];
    
    void add(int u, int v,int w,int fuv,int fvu)
    {
        e[le] = Edge(v, w, fuv, h[u]);
        h[u] = le++;
        e[le] = Edge(u, w, fvu, h[v]);
        h[v] = le++;
    }
    
    bool dfs(int x)     //判定从x是否可达终点
    {
        vis[x] = true;
        if(x == dest) return true;
        if(minfee[x] == INF)   return false;
        for(int i = h[x]; i != -1; i = e[i].next)
        {
            if(!vis[e[i].v] && minfee[x] == e[i].fee)
            {
                if(dfs(e[i].v)) return true;
                vis[e[i].v] = false;
            }
        }
        return false;
    }
    
    bool spfa(int x)
    {
        memset(d,INF,sizeof(d));
        memset(vis,false,sizeof(vis));
        memset(cnt, 0, sizeof(cnt));
        memset(minFee, INF, sizeof(minFee));
        queue<int> q;
        q.push(x);
        vis[x] = true;
        cnt[x] = 1;
        d[x] = 0;
        minFee[x] = 0;
        while(!q.empty())
        {
            int cur = q.front();
            q.pop();
            vis[cur] = false;
            for(int i = h[cur]; i != -1; i = e[i].next)
            {
                if(minfee[cur] != e[i].fee) continue;
                int v = e[i].v, w = e[i].len;
                if(minFee[v] > minFee[cur] + minfee[cur] ||(minFee[v] == minFee[cur] + minfee[cur]&&d[v] > d[cur] + w))   //先判断费用更小,再判断距离更小
                {
                    minFee[v] = minFee[cur] + minfee[cur];
                    d[v] = d[cur] + w;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        if(++cnt[v] > n)    //成环
                        {
                            if(dfs(v)) return false;    //可达终点
                            else continue;  //不可达终点
                        }
                        q.push(v);
                    }
                }
            }
        }
        return true;
    }
    
    int main()
    {
    
        while(~scanf("%d%d%d%d", &n,&m,&dept,&dest))
        {
            memset(h,-1,sizeof(h));
            memset(minfee,INF,sizeof(minfee));
            le = 0;
            char cmd[100];
            int u,v,w,fuv,fvu;
            for(int i = 0; i < m; i++)
            {
                scanf("%s",cmd);
                sscanf(cmd, "(%d,%d,%d[%d]%d)", &u,&v,&fuv,&w,&fvu);
                add(u,v,w,fuv,fvu);
                minfee[u] = min(minfee[u], fuv);
                minfee[v] = min(minfee[v], fvu);
            }
    
            memset(vis,false,sizeof(vis));
            bool VOID = !dfs(dept);
            if(VOID)    //没有路径可达
            {
                printf("VOID
    ");
                continue;
            }
            bool UNBOUND = !spfa(dept); //可达路径中存在负权费用环路
            if(UNBOUND) printf("UNBOUND
    ");
            else printf("%d %d
    ", minFee[dest], d[dest]);
        }
    
        return 0;
    }
  • 相关阅读:
    工具类-vim在shell中卡死的情况
    tomcat日志分类
    逻辑运算
    牛客练习赛29 F 算式子
    牛客练习赛29 B
    查询
    hdu 5984
    zoj 4057
    zoj 4056
    zoj 4054
  • 原文地址:https://www.cnblogs.com/TreeDream/p/5735903.html
Copyright © 2011-2022 走看看