传送门
SOL
把题看清楚,会发现从
i
i
i到
j
j
j点和返回与其他点对是相互独立的。处理出每一点对之间来回的次数,发现通过基本的贪心,只有一下几种情况:
一、全部单程。
二、优先
i
i
i到
j
j
j的双程,剩下单程。
三、优先
j
j
j到
i
i
i的双程,剩下单程。
四、优先
i
i
i到
j
j
j的双程,剩下优先优先
j
j
j到
i
i
i的双程,剩下单程。
五、优先
j
j
j到
i
i
i的双程,剩下优先优先
i
i
i到
j
j
j的双程,剩下单程。
以上五种策略分别在 四种票价大小顺序一定时最优,这是进一步贪心。
介于此题数据规模不大,代码实现上直接枚举比价就可以了。
CODE
#include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define cs const
#define ll long long
#define gc getchar()
#define in red()
inline int red(){
int num=0,f=1;char c=gc;
for(;!isdigit(c);c=gc)if(c=='-')f=-1;
for(;isdigit(c);c=gc)num=(num<<1)+(num<<3)+(c^48);
return num*f;
}
cs int N=3e6+10;
cs ll inf=1e18;
typedef pair<int,int> pi;
#define m_p make_pair
vector <int> G[N];
map <pi,int> f;
int cnt=1,n,d,m,num[2];
ll w[2][N],ans=0;
inline ll plan1(int pos){
int up=G[pos].size();
ll ret=0;
for(int i=0;i<up;++i){
ret+=w[0][pos+G[pos][i]];
}
return ret;
}
inline ll plan2(int pos){
num[0]=0;
int up=G[pos].size();
ll ret=0;
for(int i=0;i<up;++i){
bool op=G[pos][i];
if(op==1&&num[0]){
--num[0];
ret+=w[1][pos];
}
else if(op==1)ret+=w[0][pos+1];
else ++num[0];
}
ret+=w[0][pos]*num[0];
return ret;
}
inline ll plan3(int pos){
num[1]=0;
int up=G[pos].size();
ll ret=0;
for(int i=0;i<up;++i){
bool op=G[pos][i];
if(op==0&&num[1]){
--num[1];
ret+=w[1][pos+1];
}
else if(op==0)ret+=w[0][pos];
else ++num[1];
}
ret+=w[0][pos+1]*num[1];
return ret;
}
inline ll plan4(int pos,bool fer){
num[1]=num[0]=0;
int up=G[pos].size();
ll ret=0;
for(int i=0;i<up;++i){
bool op=G[pos][i];
if(op==(fer^1)&&num[fer]){
--num[fer];
ret+=w[1][pos+fer];
}
else if(op==(fer^1))++num[fer^1];
else if(op==fer)++num[fer];
}
if(num[fer]>num[fer^1])ret+=num[fer^1]*w[1][pos+(fer^1)]+(num[fer]-num[fer^1])*w[0][pos+fer];
else ret+=num[fer]*w[1][pos+(fer^1)]+(num[fer^1]-num[fer])*w[0][pos+(fer^1)];
return ret;
}
signed main(){
n=in,d=in;
int u=-1,v;
for(int i=1;i<=d;++i){
v=in;
if(u!=-1){
if(u==v)continue;
int now=f[m_p(u,v)];
if(now){
G[(now/2)*2].push_back(now-(now/2)*2);
}
else{
f[m_p(u,v)]=++cnt;
f[m_p(v,u)]=++cnt;
G[f[m_p(u,v)]].push_back(0);
}
}
u=v;
}
for(int i=2;i<=cnt;++i)w[0][i]=w[1][i]=inf;
m=in;
for(int i=1;i<=m;++i){
int u,v,p;
char t;
u=in;v=in;t=gc;p=in;
int now=f[m_p(u,v)];
if(!now)continue;
w[0][now]=min(w[0][now],1ll*p);
if(t=='R')w[1][now]=min(w[1][now],1ll*p);
}
for(int i=2;i<=cnt-1;i+=2){
ll now=plan1(i);
if(w[1][i]!=inf&&w[1][i]<w[0][i]+w[0][i+1])now=min(now,plan2(i));
if(w[1][i+1]!=inf&&w[1][i+1]<w[0][i]+w[0][i+1])now=min(now,plan3(i));
if(w[1][i]!=inf&&w[1][i+1]!=inf)now=min(min(plan4(i,0),plan4(i,1)),now);
ans+=now;
}
cout<<ans;
return 0;
}