Portal
SOL
If you look at the questions clearly, you will find that the points from iii to jjj and return are independent of each other. Deal with the number of times each pair goes back and forth, and find that through basic greed, there are only a few cases:
1. All one way.
Second, priority iii to jjj two-way, the remaining one-way.
Third, give priority to the two-way from jjj to iii, leaving one-way.
Fourth, give priority to the two-way from III to jjj, the other two-way from JJJ to iii, and the other one-way.
Fifth, give priority to the two-way from JJJ to iii, the other two-way from III to jjj, and the other one-way.
The above five strategies are optimal when the order of ticket prices is fixed, which is further greedy.
Due to the small scale of the data, it is enough to enumerate the ratio directly in the code implementation.
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; }