思路:
-啊,做得好懵…
- N种货币就是N个地点,M家“银行”就是M条路,找最长路,使用 i-th 货币时可以得到的最多钱就是 dis[i]。判断最后回到原点时可不可以得到更多钱。并且要判断是否有正环,如果有正环就能得到无限多的钱。
- 可是写的BELLMAN-FORD和SPFA运行时间完全一样啊…
- SPFA中对于 vis[i]++ 位置的判断也不知道是否正确。
- 甚至当我写了一个SLF,时间没有丝毫变化…就没有耐心写LLL了,改题再写吧。
代码:
- Bellman-Ford:141ms 688kB
//141ms 688kB
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 105;
//径:
int M;
struct node{
int U,V;
double ru,su;//rate,submission
double rv,sv;
};
node NODE[maxn];
void addnode(int i,int U,int V,double ru,double su,double rv,double sv){
NODE[i].U = U;
NODE[i].V = V;
NODE[i].ru = ru;
NODE[i].rv = rv;
NODE[i].su = su;
NODE[i].sv = sv;
return ;
}
//点:
int N;
int S;
double V;
double dis[maxn];//记录换成i-th种货币时最多能得到多少钱
bool BellmanFord(){
for(int i=1;i<=N;i++)
dis[i] = 0 ;
dis[S] = V;
int t;
for(t=1;t<=N;t++){
//(点数-1)次松弛,安排
bool book = 0;
for(int i=1;i<=M;i++){
//遍历边
if(dis[NODE[i].V] < (dis[NODE[i].U] - NODE[i].su) * NODE[i].ru){
dis[NODE[i].V] = (dis[NODE[i].U] - NODE[i].su) * NODE[i].ru;
book = 1;
}
if(dis[NODE[i].U] < (dis[NODE[i].V] - NODE[i].sv) * NODE[i].rv){
dis[NODE[i].U] = (dis[NODE[i].V] - NODE[i].sv) * NODE[i].rv;
book = 1;
}
}
if(!book)
break;
}
if(t > N)
return true ; //有正环,可以无限增大
if(dis[S] > V)
return true ;
return false;
}
int main(){
cin>>N>>M>>S>>V;
for(int i=1;i<=M;i++){
int a,b;double c,d,e,f;
cin>>a>>b>>c>>d>>e>>f;
addnode(i,a,b,c,d,e,f);
}
if(BellmanFord())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
return 0;
}
- SPFA:关于 vis[i]++ 的两种形式:141ms
//141ms 680kB
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 105;
//点:
int N,S;
double V;
double dis[maxn];
int vis[maxn];//记录点的入队次数
bool book[maxn];//记录点是否在队列中
struct NODE{
int id;
int dis;
NODE(int id,int dis) : id(id) , dis(dis) {} ;
};
deque<NODE> D;
//径:
int M;
struct PATH{
int a,b;
double ra,sa,rb,sb;
};
PATH P[maxn];
void addpath(int i,int a,int b,double c,double d,double e,double f){
P[i].a = a;
P[i].b = b;
P[i].ra = c;
P[i].sa = d;
P[i].rb = e;
P[i].sb = f;
return ;
}
bool SPFA(){
for(int i=1;i<=N;i++)
dis[i]=0,vis[i]=0;
D.push_back(NODE(S,V));vis[S]=1;dis[S]=V;book[S]=true;
while(D.size()){
NODE cur = D.front();D.pop_front();book[cur.id]=false;
for(int i=1;i<=M;i++){
if(P[i].a == cur.id){
if(dis[P[i].b] < (dis[P[i].a] - P[i].sa) * P[i].ra){
dis[P[i].b] = (dis[P[i].a] - P[i].sa) * P[i].ra;
if(!book[P[i].b]){
D.push_back(NODE(P[i].b , dis[P[i].b]));
book[P[i].b] = true;
vis[P[i].b]++;
//为什么队列中有点时仅更新不加松弛次数:
//因为无法修改队列中已有的点,可能会有某些点被同一个点反复松弛。
//但是,我把vis[P[i].b]++放到判断外面也AC了,姑且认为是数据不强,若以后弄明白会再来补。
if(vis[P[i].b] == N)
return true;
}
}
}
if(P[i].b == cur.id){
if(dis[P[i].a] < (dis[P[i].b] - P[i].sb) * P[i].rb){
dis[P[i].a] = (dis[P[i].b] - P[i].sb) * P[i].rb;
if(!book[P[i].a]){
D.push_back(NODE(P[i].a , dis[P[i].a]));
book[P[i].a] = true;
vis[P[i].a]++;
if(vis[P[i].a] == N)
return true;
}
}
}
}
}
if(dis[S] != V)
return true;
return false;
}
int main(){
cin>>N>>M>>S>>V;
for(int i=1;i<=M;i++){
int a,b;
double c,d,e,f;
cin>>a>>b>>c>>d>>e>>f;
addpath(i,a,b,c,d,e,f);
}
if(SPFA())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
return 0;
}
//141ms 676kB
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 105;
//点:
int N,S;
double V;
double dis[maxn];
int vis[maxn];//记录点的入队次数
bool book[maxn];//记录点是否在队列中
struct NODE{
int id;
double *dis;
NODE(int id,double *dis) : id(id) , dis(dis) {} ;
};
deque<NODE> D;
//径:
int M;
struct PATH{
int a,b;
double ra,sa,rb,sb;
};
PATH P[maxn];
void addpath(int i,int a,int b,double c,double d,double e,double f){
P[i].a = a;
P[i].b = b;
P[i].ra = c;
P[i].sa = d;
P[i].rb = e;
P[i].sb = f;
return ;
}
bool SPFA(){
for(int i=1;i<=N;i++)
dis[i]=0,vis[i]=0;
D.push_back(NODE(S,&dis[S]));vis[S]=1;dis[S]=V;book[S]=true;
while(D.size()){
NODE cur = D.front();D.pop_front();book[cur.id]=false;
for(int i=1;i<=M;i++){
if(P[i].a == cur.id){
if(dis[P[i].b] < (dis[P[i].a] - P[i].sa) * P[i].ra){
dis[P[i].b] = (dis[P[i].a] - P[i].sa) * P[i].ra;
vis[P[i].b]++;
if(!book[P[i].b]){
D.push_back(NODE(P[i].b , &dis[P[i].b]));
book[P[i].b] = true;
if(vis[P[i].b] == N)
return true;
}
}
}
if(P[i].b == cur.id){
if(dis[P[i].a] < (dis[P[i].b] - P[i].sb) * P[i].rb){
dis[P[i].a] = (dis[P[i].b] - P[i].sb) * P[i].rb;
vis[P[i].a]++;
if(!book[P[i].a]){
D.push_back(NODE(P[i].a , &dis[P[i].a]));
book[P[i].a] = true;
vis[P[i].a]++;
if(vis[P[i].a] == N)
return true;
}
}
}
}
}
if(dis[S] != V)
return true;
return false;
}
int main(){
cin>>N>>M>>S>>V;
for(int i=1;i<=M;i++){
int a,b;
double c,d,e,f;
cin>>a>>b>>c>>d>>e>>f;
addpath(i,a,b,c,d,e,f);
}
if(SPFA())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
return 0;
}