Wormholes (负权路)
题目链接: F - Wormholes POJ - 3259
题意
有许多虫洞,可以回到过去(单向)农场主想要回到过去,给你一个图,里面包含了普通的最短路和虫洞,问你,农场主能否回到过去
思路
这是一道典型的负权最短路问题,标准的做法应该是用Bellmen_ford吧,不过,我第一次做没有使用。我在先前做Djs的时候就一直在想,如果这里面出现了负权路是不是就会无限循环了呢,答案是YES,所以我利用了这一点对DJS进行了变化, 因为是无限循环嘛,所以我就定义了一个很大的数NumMax,在循环达到了一定程度就退出循环,返回这是个负权图,十分简单粗暴。
这样我是不是算发明了新算法呢,好了,我需要再对其进行规范化,这里还有好几处需要优化的地方。
- 这个NumMax该定义多大了,我第一次过是用1e6的 1963ms 真的是在 TLE 的边缘试探,我将其改小了一些,当变成1e5时变成了300ms,当变成1e4时变成了180ms。最后我定在了2572左右过了这个值到底跟什么因素有关系呢,我还得再研究。
- 第二点的话我觉得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");
}
}
}