[kuangbin带你飞] - Wormholes (负权路)

Wormholes (负权路)

题目链接: F - Wormholes POJ - 3259

题意

有许多虫洞,可以回到过去(单向)农场主想要回到过去,给你一个图,里面包含了普通的最短路和虫洞,问你,农场主能否回到过去


思路

这是一道典型的负权最短路问题,标准的做法应该是用Bellmen_ford吧,不过,我第一次做没有使用。我在先前做Djs的时候就一直在想,如果这里面出现了负权路是不是就会无限循环了呢,答案是YES,所以我利用了这一点对DJS进行了变化, 因为是无限循环嘛,所以我就定义了一个很大的数NumMax,在循环达到了一定程度就退出循环,返回这是个负权图,十分简单粗暴。

这样我是不是算发明了新算法呢,好了,我需要再对其进行规范化,这里还有好几处需要优化的地方。

  1. 这个NumMax该定义多大了,我第一次过是用1e6的 1963ms 真的是在 TLE 的边缘试探,我将其改小了一些,当变成1e5时变成了300ms,当变成1e4时变成了180ms。最后我定在了2572左右过了这个值到底跟什么因素有关系呢,我还得再研究。
  2. 第二点的话我觉得vector还可以进行优化,因为使用了vector的原因,这里面塞了一些无用的数据,本来从点1到点2我们只需要最短的那条就行了,然而用了vector比较难以优化,我想离散化来着的,但好像很困难。。。。因为如果离散化成功了,那么每个点应该只会经过一次,经过第二次时其实就已经出现负环了。

优化

    //将其进行离散化,如果有大量的重边时,值得一试
/*
    并且,在离散以后,出现负环的情况就非常好判断了
    1)总循环出现的次数大于N*N
    2)某个点出现的次数大于N-1
*/
bool cmp(const Node&a,const Node&b){
    return a.to!=b.to?a.to < b.to:a.cost<b.cost;
}
bool cmp2(const Node&a,const Node&b){
    return a.cost < b.cost;
}
void DeV(){
    vector<Node> vp[1];
    vp[0].pb(Node(0,INF)); //这里的INF和 
    G[0].pb(Node(0,INF)); //根据实际情况调整
    rep(i,1,N) {
        sort(G[i].begin(),G[i].end(),cmp);
        rep(j,1,sz(G[i])-1)  if (G[i][j].to == G[i][j-1].to) G[i][j].cost = INF;
        sort(G[i].begin(),G[i].end(),cmp2);
        G[i].erase(lower_bound(G[i].begin(),G[i].end(),G[0][0],cmp2),G[i].end());
    }
}

代码

/*
Time : 47
Mem  : 780
*/
#include <iomanip>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <string>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <sstream>
#include <memory>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define rep(i,j,k) for(int i = (int)(j);i <= (int)(k);i ++)
#define per(i,j,k) for(int i = (int)(j);i >= (int)(k);i --)
#define mmm(a,b)   memset(a,b,sizeof(a))
#define sz(x) ((int)(x).size())
#define pb push_back

typedef double db;
typedef long long ll;
const int INF = (int)0x3f3f3f3f;
const int MAXN = (int)5e2+7;

struct Node {
    int to,cost;
    Node(int t=0,int c=0):to(t),cost(c){}
};
vector <Node> G[MAXN];
queue <int> qu;
int dis[MAXN];
int N,M,W;

bool Djs(){
    qu.push(1);
    dis[1] = 0;
    int cnt = 0;
    while (!qu.empty()) {
        cnt ++;
        if (cnt == 2572) return true;
        int k = qu.front();
        qu.pop();

        rep(i,0,sz(G[k])-1){
            int to = G[k][i].to;
            int co = G[k][i].cost;
            if (dis[to] > dis[k] + co){
                dis[to] = dis[k] + co;
                qu.push(to);
            }
        }
    }
    return false;
}

void init(){
    mmm(dis,0x3f);
    rep(i,1,N)G[i].clear();
    while (!qu.empty()) qu.pop();
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T --){
        init();
        scanf("%d %d %d",&N,&M,&W);
        rep(i,1,M){
            int x,y,c;
            scanf("%d %d %d",&x,&y,&c);
            G[x].pb(Node(y,c));
            G[y].pb(Node(x,c));
        }

        rep(i,1,W){
            int x,y,c;
            scanf("%d %d %d",&x,&y,&c);
            G[x].pb(Node(y,-c));
        }

        if (Djs()){
            printf("YES\n");
        }else {
            printf("NO\n");
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41428565/article/details/80245655