写在前面的话:关于SLF(斯拉夫)和LLL(treple long)优化(自己用的昵称),详见QAQqwe的BLOG。
总结:
-
本题先后写了:
邻接矩阵:Bell、SPFA、SPFA+SLF;
邻接表:SPFA、SPFA+SLF、SPFA+SLF、SPFA+SLF+LLL。 -
结论:(仅针对我自己,我也不知道为什么大家都是SPFA更快,我也不知道为什么大家都可以做到SLF和LLL的优化)
邻接表要快一些。
Bell比SPFA快。
SLF和LLL都让时间增加。 SPFA+SLF+LLL一定T。
思路:
- 正权,单向,找正环(最长路)。
- SPFA:队列中存的是 id。
- SLF优化:
- 最重要的是 Q.size(),没它一定 RE。
- 最短路中,dis 小放前面;最长路中:dis 大放前面。
代码:
- BELL:735ms 712kB
//735ms 712kB
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
const int maxn = 35;
int T=0;
int N;
map<string,int> MP;
int M;
double exmp[maxn][maxn];
double dis[maxn];
void INIT(){
for(int i=1;i<maxn;i++){
for(int j=1;j<maxn;j++)
exmp[i][j]=0;
exmp[i][i] = 1;
}
MP.clear();
for(int i=1;i<maxn;i++)
dis[i]=0;
}
bool BELL(){
dis[1] = 1;
int t;
for(t=1;t<=N;t++){
bool flag = false;
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(dis[j] < dis[i] * exmp[i][j]){
dis[j] = dis[i] * exmp[i][j];
flag = true;
}
}
}
if(!flag)
break;
}
if(t>N)
return true;
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>N && N){
T++;
INIT();
for(int i=1;i<=N;i++){
string name;
cin>>name;
if(!MP.count(name))
MP[name] = i;
}
cin>>M;
for(int i=1;i<=M;i++){
string A,B;
double rate;
cin>>A>>rate>>B;
exmp[MP[A]][MP[B]] = max(exmp[MP[A]][MP[B]] , rate);
}
if(BELL())
cout<<"Case "<<T<<": "<<"Yes"<<endl;
else
cout<<"Case "<<T<<": "<<"No"<<endl;
}
return 0;
}
- SPFA:797ms 728kB
//797ms 728kB
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
using namespace std;
const int maxn = 35;
int T;
int N,M;
map<string,int> MP;
queue<int> D;
double dis[maxn];
bool vis[maxn];
int cnt[maxn];
double exmp[maxn][maxn];
void INIT(){
MP.clear();
while(D.size())
D.pop();
for(int i=1;i<maxn;i++)
dis[i] = 0,cnt[i] = 0,vis[i]=0;
for(int i=1;i<maxn;i++)
for(int j=1;j<maxn;j++)
exmp[i][j] = 0;
return ;
}
bool SPFA(){
dis[1] = 1;
D.push(1);vis[1] = true;
while(D.size()){
int cur = D.front() ; D.pop();vis[cur]=0;
for(int i=1;i<=N;i++){
if(exmp[cur][i])
if(dis[i] < dis[cur] * exmp[cur][i]){
dis[i] = dis[cur] * exmp[cur][i];
if(!vis[i]){
D.push(i);
cnt[i]++;
if(cnt[i] == N)
return true;
vis[i] = true;
}
}
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>N && N){
T++;
INIT();
for(int i=1;i<=N;i++){
string name;
cin>>name;
MP[name] = i;
}
cin>>M;
for(int i=1;i<=M;i++){
string A,B;
double rate;
cin>>A>>rate>>B;
exmp[MP[A]][MP[B]] = max(exmp[MP[A]][MP[B]] , rate);
}
if(SPFA())
cout<<"Case "<<T<<": "<<"Yes"<<endl;
else
cout<<"Case "<<T<<": "<<"No"<<endl;
}
return 0;
}
- SPFA+SLF:844ms 740kB
//844ms 740kB
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
using namespace std;
const int maxn = 35;
int T;
int N,M;
map<string,int> MP;
deque<int> D;
double dis[maxn];
bool vis[maxn];
int cnt[maxn];
double exmp[maxn][maxn];
void INIT(){
MP.clear();
while(D.size())
D.pop_front();
for(int i=1;i<maxn;i++)
dis[i] = 0,cnt[i] = 0,vis[i]=0;
for(int i=1;i<maxn;i++)
for(int j=1;j<maxn;j++)
exmp[i][j] = 0;
return ;
}
bool SPFA(){
dis[1] = 1;
D.push_front(1);vis[1] = true;
while(D.size()){
int cur = D.front() ; D.pop_front();vis[cur]=0;
for(int i=1;i<=N;i++){
if(exmp[cur][i])
if(dis[i] < dis[cur] * exmp[cur][i]){
dis[i] = dis[cur] * exmp[cur][i];
if(!vis[i]){
if(D.size() && dis[i] < dis[D.front()])
//注意D.size()不加会RE
D.push_front(i);
else
D.push_back(i);
cnt[i]++;
if(cnt[i] == N)
return true;
vis[i] = true;
}
}
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>N && N){
T++;
INIT();
for(int i=1;i<=N;i++){
string name;
cin>>name;
MP[name] = i;
}
cin>>M;
for(int i=1;i<=M;i++){
string A,B;
double rate;
cin>>A>>rate>>B;
exmp[MP[A]][MP[B]] = max(exmp[MP[A]][MP[B]] , rate);
}
if(SPFA())
cout<<"Case "<<T<<": "<<"Yes"<<endl;
else
cout<<"Case "<<T<<": "<<"No"<<endl;
}
return 0;
}
- 邻接表+SPFA:750ms 752kB
//750ms 752kB
#include <iostream>
#include <queue>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
const int maxn = 305;
int T=0;
int N,M;
deque<int> Q;
map<string,int> MP;//name & id
struct EDGE{
int to;
double r;
int fo;
};
EDGE E[maxn * 10];
int tail[maxn];
double dis[maxn];
bool vis[maxn];
int cnt[maxn];
void ADDEDGE(int i,int u,int v,double w){
E[i].to = v;
E[i].r = w;
E[i].fo = tail[u];
tail[u] = i;
return ;
}
void INIT(){
for(int i=1;i<maxn;i++)
tail[i] = -1 , dis[i] = 0 , vis[i] = 0 , cnt[i] = 0;
}
bool SPFA(){
dis[1] = 1;
Q.push_back(1);vis[1] = 1;
while(Q.size()){
int cur = Q.front();Q.pop_front();vis[cur]=0;
for(int i=tail[cur] ; ~i ; i=E[i].fo){
int v = E[i].to;
if(dis[v] < dis[cur] * E[i].r){
dis[v] = dis[cur] * E[i].r;
if(!vis[v]){
Q.push_back(v);vis[v]=1;
cnt[v]++;
if(cnt[v] == N)
return true;
}
}
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>N && N){
T++;
INIT();
for(int i=1;i<=N;i++){
string name;
cin>>name;
MP[name] = i;
}
cin>>M;
for(int i=1;i<=M;i++){
string A,B;
double r;
cin>>A>>r>>B;
ADDEDGE(i , MP[A] , MP[B] , r);
}
if(SPFA())
cout<<"Case "<<T<<": "<<"Yes"<<endl;
else
cout<<"Case "<<T<<": "<<"No"<<endl;
}
return 0;
}
- 邻接表+SPFA+SLF:782ms 736kB
//782ms 736kB
#include <iostream>
#include <queue>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
const int maxn = 305;
int T=0;
int N,M;
deque<int> Q;
map<string,int> MP;//name & id
struct EDGE{
int to;
double r;
int fo;
};
EDGE E[maxn * 10];
int tail[maxn];
double dis[maxn];
bool vis[maxn];
int cnt[maxn];
void ADDEDGE(int i,int u,int v,double w){
E[i].to = v;
E[i].r = w;
E[i].fo = tail[u];
tail[u] = i;
return ;
}
void INIT(){
for(int i=1;i<maxn;i++)
tail[i] = -1 , dis[i] = 0 , vis[i] = 0 , cnt[i] = 0;
}
bool SPFA(){
dis[1] = 1;
Q.push_back(1);vis[1] = 1;
while(Q.size()){
int cur = Q.front();Q.pop_front();vis[cur]=0;
for(int i=tail[cur] ; ~i ; i=E[i].fo){
int v = E[i].to;
if(dis[v] < dis[cur] * E[i].r){
dis[v] = dis[cur] * E[i].r;
if(!vis[v]){
vis[v]=1;
if(Q.size() && dis[Q.front()] < dis[v])
Q.push_front(v);
else
Q.push_back(v);
cnt[v]++;
if(cnt[v] == N)
return true;
}
}
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>N && N){
T++;
INIT();
for(int i=1;i<=N;i++){
string name;
cin>>name;
MP[name] = i;
}
cin>>M;
for(int i=1;i<=M;i++){
string A,B;
double r;
cin>>A>>r>>B;
ADDEDGE(i , MP[A] , MP[B] , r);
}
if(SPFA())
cout<<"Case "<<T<<": "<<"Yes"<<endl;
else
cout<<"Case "<<T<<": "<<"No"<<endl;
}
return 0;
}
- 邻接表+SPFA+SLF+LLL:TLE
//TLE
#include <iostream>
#include <queue>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
const int maxn = 305;
int T=0;
int N,M;
deque<int> Q;
map<string,int> MP;//name & id
struct EDGE{
int to;
double r;
int fo;
};
EDGE E[maxn * 10];
int tail[maxn];
double dis[maxn];
bool vis[maxn];
int cnt[maxn];
double sum;
void ADDEDGE(int i,int u,int v,double w){
E[i].to = v;
E[i].r = w;
E[i].fo = tail[u];
tail[u] = i;
return ;
}
void INIT(){
for(int i=1;i<maxn;i++)
tail[i] = -1 , dis[i] = 0 , vis[i] = 0 , cnt[i] = 0;
return ;
}
bool SPFA(){
dis[1] = 1;
Q.push_back(1);vis[1] = 1;sum = 1;
while(Q.size()){
int cur = Q.front();
int num = Q.size();
while(dis[cur] * num < sum){
Q.pop_front();
Q.push_back(cur);
cur = Q.front();
}
Q.pop_front();
vis[cur]=0;
sum -= dis[cur];
for(int i=tail[cur] ; ~i ; i=E[i].fo){
int v = E[i].to;
if(dis[v] < dis[cur] * E[i].r){
dis[v] = dis[cur] * E[i].r;
if(!vis[v]){
vis[v]=1;
if(Q.size() && dis[Q.front()] < dis[v])
Q.push_front(v);
else
Q.push_back(v);
sum += dis[v];
cnt[v]++;
if(cnt[v] == N)
return true;
}
}
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>N && N){
T++;
INIT();
for(int i=1;i<=N;i++){
string name;
cin>>name;
MP[name] = i;
}
cin>>M;
for(int i=1;i<=M;i++){
string A,B;
double r;
cin>>A>>r>>B;
ADDEDGE(i , MP[A] , MP[B] , r);
}
if(SPFA())
cout<<"Case "<<T<<": "<<"Yes"<<endl;
else
cout<<"Case "<<T<<": "<<"No"<<endl;
}
return 0;
}