[SPFA (Bellman Ford)] POJ 1860 Currency Exchange | POJ 3259 Wormholes | LightOJ 1074 Extended
POJ 1860 Currency Exchange | POJ 3259 Wormholes | LightOJ 1074 Extended Traffic
SPFA (Bellman Ford)
POJ 1860 Currency Exchange
#include"stdio.h"
#include"string.h"
#include"math.h"
#include
#include
#include
#include
using namespace std;
typedef pair Pair;
typedef pair PairDI;
const int MAX_NM=103;
const int MAX_V=1003;
int N;// n currency, 1-indexed
int M;// n ExPoints
int S;
double V;
Pair G[MAX_NM][MAX_NM];
double dis[MAX_NM];
bool vis[MAX_NM];
int cnt[MAX_NM];
bool SPFA(int S){
dis[S]=V;
priority_queue Q;// max heap
Q.push(PairDI(dis[S],S));
vis[S]=true;
++cnt[S];
while(!Q.empty()){
PairDI p = Q.top();
Q.pop();
int cur = p.second;
vis[cur]=false;
for(int i=1;i<=N;i++){
if(G[cur][i].first==0.0) continue;// no path
double r = G[cur][i].first;
double c = G[cur][i].second;
if((dis[cur]-c)*r > dis[i]){
// printf("%d %d\n", cur,i);
dis[i] = (dis[cur]-c)*r;
if(!vis[cur]){
Q.push(Pair(dis[i],i));
vis[i]=true;
if(++cnt[i] > N-1) return true;
}
}
}
}
return false;// 不存在“负权环”
}
int main(){
fill(G[0],G[0]+MAX_NM*MAX_NM,Pair(0,0));
fill(dis,dis+MAX_NM,0);
fill(vis,vis+MAX_NM,false);
fill(cnt,cnt+MAX_NM,0);
scanf("%d%d%d%lf",&N,&M,&S,&V);
for(int m=0;m
POJ 3259 Wormholes
- 判断是否存在负环(从任源点出发),每个节点作源进行SPFA显然会TLE。
- 只进行一次单源SPFA:
- 添加辅助顶点C,有向边S->C,有向边C->v (其中v∈V - {S} )。即可只进行一次单源SPFA;
- 同时防止因添加顶点C引入了负环,因此:
- 这些有向边的权重ω要足够大,满足2ω>MAX_NW(负权边的绝对值的最大值)。
/* #include 省略 */
typedef pair Pair;
const int MAX_N = 503;
int N;// fields, 1~500
int M;// paths
int W;// wormholes
int G[MAX_N][MAX_N];
int dis[MAX_N];
bool vis[MAX_N];
int cnt[MAX_N];
bool SPFA(int s){
dis[s]=0;
priority_queue,greater> Q;// min heap
Q.push(Pair(dis[s],s));
vis[s]=true;
cnt[s]++;
while(!Q.empty()){
Pair p = Q.top();
Q.pop();
int cur = p.second;
vis[cur]=false;
for(int i=1;i<=N+1;i++){
if(G[cur][i]>10000) continue;
if(dis[cur]+G[cur][i] < dis[i]){
// printf("%d %d\n", cur,i);
dis[i] = dis[cur]+G[cur][i];
if(!vis[cur]){
Q.push(Pair(dis[i],i));
vis[i]=true;
if(++cnt[i] > N+1-1) return true;
}
}
}
}
return false;
}
int main(){
int F;
scanf("%d",&F);
for(int f=0;f10000)? T : min(G[S][E],T);
}
for(int w=0;w10000)? (-1)*T : min(G[S][E],(-1)*T);
}
// 辅助节点到各节点的边权设置
G[1][N+1]=10000;
for(int i=2;i<=N;i++) G[N+1][i]=10000;
fill(dis,dis+MAX_N,999999999);
fill(vis,vis+MAX_N,false);
fill(cnt,cnt+MAX_N,0);
if(SPFA(1)) printf("YES\n");
else printf("NO\n");
}
return 0;
}
LightOJ 1074 Extended Traffic
相较于判断是否存在负环,不同之处在于
typedef pair Pair;
const int INF=0x3fffffff;
const int MAX_N=203;
int N;// n junction
int M;// n roads
int Q;// n queries
int bsns[MAX_N];
int G[MAX_N][MAX_N];
int dis[MAX_N];
int vis[MAX_N];
int cnt[MAX_N];
int cube(int src,int dst){// how to deal with negative val
int tmp = bsns[dst]-bsns[src];
return tmp*tmp*tmp;
}
void spfa(){
dis[1]=0;
priority_queue,greater > Q;// min heap
Q.push(Pair(dis[1],1));
vis[1]=1;
cnt[1]++;
while(!Q.empty()){
Pair p = Q.top();
Q.pop();
int cur = p.second;
vis[cur]=0;
for(int i=1;i<=N;i++){
if(G[cur][i]==0) continue;
if(dis[cur] + cube(cur,i) < dis[i]){
dis[i] = dis[cur] + cube(cur,i);
if(!vis[i]) {
// 当发现有负环时不应return,而是continue
// 应使负环可达的所有点的cnt都 > N-1
if(cnt[i]++ > N-1) continue;
Q.push(Pair(dis[i],i));
vis[i]=1;
// 判断是否存在负环的模板做法:
// if(cnt[i]++ > N-1) return;
}
}
}
}
return;
}
int main(){
int T;
scanf("%d",&T);
for(int t=1;t<=T;t++){
fill(G[0],G[0]+MAX_N*MAX_N,0);fill(dis,dis+MAX_N,INF);fill(vis,vis+MAX_N,0);
fill(cnt,cnt+MAX_N,0);
scanf("%d",&N);
for(int n=1;n<=N;n++) scanf("%d",&bsns[n]);
scanf("%d",&M);
for(int m=1;m<=M;m++){
int src,dst; scanf("%d %d",&src,&dst);
G[src][dst]=1;// uni-directional
}
spfa();
printf("Case %d:\n", t);
scanf("%d",&Q);
for(int q=0;qN-1
if(dis[x]<3 || dis[x]==INF ||cnt[x]>N-1) printf("?\n");
else printf("%d\n", dis[x]);
}
}
return 0;
}