算法分析:
[ ]
Ac代码如下:
这道题是求最长路。采用一个玄学优化:
将新入队节点分为两类,边为正值加到队头,边为负值加到队尾
#pragma GCC optimize(2)
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <deque>
#include <stack>
using namespace std;
const int N = 100005;
const int K = 200005;
int h[N], ne[K], egs[K], egw[K];
//int ingre[N];
int idx;
int dis[N];
int exst[N];
int cnt[N];
int n, k;
void add(int a, int b, int c){
ne[++idx] = h[a];
h[a] = idx;
egs[idx] = b;
egw[idx] = c;
}
long long spfa(){
deque<int> q;
for(int i = 1; i <= n; i++){
dis[i] = 1;
q.push_back(i);
exst[i] = 1;
}
while(q.size()){
int u = q.front();
q.pop_front();
exst[u] = 0;
for(int cre = h[u]; cre; cre = ne[cre]){
int v = egs[cre];
int w = egw[cre];
int nw = dis[u] + w;
if(nw > dis[v]){
dis[v] = nw;
cnt[v] = cnt[u]+1;
if(!exst[v]){
if(egw[cre] < 0)q.push_back(v);
else q.push_front(v);
}
if(cnt[v] > n)
return -1;
}
}
}
long long ans= 0;
for(int i =1 ; i <= n; i++){
ans += dis[i];
}
return ans;
}
int main(void){
scanf("%d%d", &n, &k);
// uno_init();
for(int i = 0; i < k; i++){
int x, a, b;
scanf("%d%d%d", &x,&a, &b);
switch(x){
case 1:
add(a, b, 0);
add(b, a, 0);
// ingre[a]++, intgre[b]++;
break;
case 2:
add(a, b, 1);
// add(b, a, 1);
break;
case 3:
add(b, a, 0);
break;
case 4:
add(b, a, 1);
break;
case 5:
add(a, b, 0);
break;
}
}
printf("%lld", spfa());
}
bro,你这个双端队列就相当于一个栈啊,因为你建的图里面根本就没有负权边,用SPFA用栈可以更快的判断是否存在环。
你说的对,确实是个栈,我写的时候只按照进阶指南上说的那种优化写了,没有想到这里还是个栈😂