https://www.patest.cn/contests/pat-a-practise/1087
在求最短路径种数的时候,是这样写的:
#include<bits/stdc++.h>
using namespace std;
int n,m,ed,a;
string st,z,y;
map<string,int> r;
struct node{
string a;
int b;
}x[205];
int w[205][205];
int path[205];
int num[205];
int happy[205];
int cost[205];
int main(){
cin>>n>>m>>st;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
w[i][j]=100000000;
}
}
x[0].a=st;
r[st]=0;
for(int i=1;i<n;++i){
cin>>x[i].a>>x[i].b;
if(x[i].a=="ROM")
ed=i;
r[x[i].a]=i;
}
while(m--){
cin>>y>>z>>a;
w[r[y]][r[z]]=a;
w[r[z]][r[y]]=a;
}
for(int i=0;i<n;++i){
cost[i]=100000000;
}
priority_queue<int> q;
q.push(0);
cost[0]=0;
int costs=100000000,happys=-1,nums=100000000,sum=-1,p;
while(!q.empty()){
int fr=q.top();
q.pop();
if(fr==ed){
if(cost[fr]<costs||
(cost[fr]==costs&&happy[fr]>happys)||
(cost[fr]==costs&&happy[fr]==happys&&num[fr]<nums)){
costs=cost[fr];
happys=happy[fr];
nums=num[fr];
p=fr;
}
if(cost[fr]<costs)
sum=1;
else if(cost[fr]==costs)
sum++;
continue;
}
for(int i=0;i<n;++i){
if(cost[fr]+w[fr][i]<=cost[i]){
cost[i]=cost[fr]+w[fr][i];
if(happy[fr]+x[i].b>happy[i]||
(happy[fr]+x[i].b==happy[i]&&num[fr]+1<num[i])){
happy[i]=happy[fr]+x[i].b;
num[i]=num[fr]+1;
path[i]=fr;
}
q.push(i);
}
}
}
cout<<sum<<" "<<costs<<" "<<happys<<" "<<happys/nums<<endl;
stack<int> st;
st.push(ed);
while(ed!=0){
ed=path[ed];
st.push(ed);
}
while(!st.empty()){
cout<<x[st.top()].a;
st.pop();
if(st.empty())
cout<<endl;
else
cout<<"->";
}
}
然后就因为这个【
最短路径种数】和【内存超限】报错了。
修改之后是这样写的:
#include<bits/stdc++.h>
using namespace std;
int n,m,ed,a;
string st,z,y;
map<string,int> r;
struct node{
string a;
int b;
}x[205];
int w[205][205];
int path[205];
int num[205];
int happy[205];
int cost[205];
int over[205];
int main(){
cin>>n>>m>>st;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
w[i][j]=100000000;
}
}
x[0].a=st;
r[st]=0;
for(int i=1;i<n;++i){
cin>>x[i].a>>x[i].b;
if(x[i].a=="ROM")
ed=i;
r[x[i].a]=i;
}
while(m--){
cin>>y>>z>>a;
w[r[y]][r[z]]=a;
w[r[z]][r[y]]=a;
}
for(int i=0;i<n;++i){
cost[i]=100000000;
}
priority_queue<int> q;
q.push(0);
cost[0]=0;
over[0]=1;
int costs=100000000,happys=-1,nums=100000000,sum=-1,p;
while(!q.empty()){
int fr=q.top();
q.pop();
if(fr==ed){
if(cost[fr]<costs||
(cost[fr]==costs&&happy[fr]>happys)||
(cost[fr]==costs&&happy[fr]==happys&&num[fr]<nums)){
costs=cost[fr];
happys=happy[fr];
nums=num[fr];
p=fr;
}
if(cost[fr]<costs)
sum=1;
else if(cost[fr]==costs)
sum++;
continue;
}
for(int i=0;i<n;++i){
if(cost[fr]+w[fr][i]<=cost[i]){
if(happy[fr]+x[i].b>happy[i]||
(happy[fr]+x[i].b==happy[i]&&num[fr]+1<num[i])){
happy[i]=happy[fr]+x[i].b;
num[i]=num[fr]+1;
path[i]=fr;
}
if(cost[i]==cost[fr]+w[fr][i]){
over[i]+=over[fr];
}
else{
q.push(i);
over[i]=over[fr];
cost[i]=cost[fr]+w[fr][i];
}
}
}
}
cout<<over[ed]<<" "<<costs<<" "<<happys<<" "<<happys/nums<<endl;
stack<int> st;
st.push(ed);
while(ed!=0){
ed=path[ed];
st.push(ed);
}
while(!st.empty()){
cout<<x[st.top()].a;
st.pop();
if(st.empty())
cout<<endl;
else
cout<<"->";
}
}
一开始以为【内存超限】是因为我没有把费用相同的路径合并计算(即第一个代码),但其实不是这个原因,而是我的Dijkstra是优先队列nlogn版的……改成了n2的版本就过了。
#include<bits/stdc++.h>
using namespace std;
int n,m,ed,a;
string st,z,y;
map<string,int> r;
struct node{
string a;
int b;
}x[205];
int w[205][205];
int path[205];
int num[205];
int happy[205];
int cost[205];
int over[205];
int main(){
cin>>n>>m>>st;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
w[i][j]=100000000;
}
}
x[0].a=st;
r[st]=0;
for(int i=1;i<n;++i){
cin>>x[i].a>>x[i].b;
if(x[i].a=="ROM")
ed=i;
r[x[i].a]=i;
}
while(m--){
cin>>y>>z>>a;
w[r[y]][r[z]]=a;
w[r[z]][r[y]]=a;
}
for(int i=0;i<n;++i){
cost[i]=100000000;
}
cost[0]=0;
over[0]=1;
int vis[205]={0};
int costs=100000000,happys=-1,nums=100000000,p;
for(int nn=0;nn<n;++nn){
int fr;
int minn=100000000;
for(int i=0;i<n;++i){
if(vis[i]==1) continue; //这步千万别忘啊!!
if(cost[i]<minn){
minn=cost[i];
fr=i;
}
}
vis[fr]=1; //这步千万别忘啊!!
if(fr==ed){
if(cost[fr]<costs||
(cost[fr]==costs&&happy[fr]>happys)||
(cost[fr]==costs&&happy[fr]==happys&&num[fr]<nums)){
costs=cost[fr];
happys=happy[fr];
nums=num[fr];
p=fr;
}
continue;
}
for(int i=0;i<n;++i){
if(vis[i]==1) continue; //这步千万别忘啊!!
if(cost[fr]+w[fr][i]<=cost[i]){
if(cost[fr]+w[fr][i]<cost[i]||
(cost[fr]+w[fr][i]==cost[i]&&happy[fr]+x[i].b>happy[i])||
(cost[fr]+w[fr][i]==cost[i]&&happy[fr]+x[i].b==happy[i]&&num[fr]+1<num[i])){
happy[i]=happy[fr]+x[i].b;
num[i]=num[fr]+1;
path[i]=fr;
}
if(cost[i]==cost[fr]+w[fr][i]){
over[i]+=over[fr];
}
else{
over[i]=over[fr];
cost[i]=cost[fr]+w[fr][i];
}
}
}
}
cout<<over[ed]<<" "<<costs<<" "<<happys<<" "<<happys/nums<<endl;
stack<int> st;
st.push(ed);
while(ed!=0){
ed=path[ed];
st.push(ed);
}
while(!st.empty()){
cout<<x[st.top()].a;
st.pop();
if(st.empty())
cout<<endl;
else
cout<<"->";
}
}
然后再仔细一看——哎呀原来内存超限的根本原因是优先队列根本就忘了用到“优先”了!( ̄_ ̄╬
于是,最完美的版本如下:
#include<bits/stdc++.h>
using namespace std;
int n,m,ed,a;
string st,z,y;
map<string,int> r;
struct node{
string a;
int b;
}x[205];
int w[205][205];
int path[205];
int num[205];
int happy[205];
int cost[205];
int over[205];
struct cmp{
bool operator()(const int &t1,const int &t2){
return cost[t1]>cost[t2]; //从小到小=大,与数组规则相反
}
};
int main(){
cin>>n>>m>>st;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
w[i][j]=100000000;
}
}
x[0].a=st;
r[st]=0;
for(int i=1;i<n;++i){
cin>>x[i].a>>x[i].b;
if(x[i].a=="ROM")
ed=i;
r[x[i].a]=i;
}
while(m--){
cin>>y>>z>>a;
w[r[y]][r[z]]=a;
w[r[z]][r[y]]=a;
}
for(int i=0;i<n;++i){
cost[i]=100000000;
}
priority_queue<int,vector<int>,cmp> q;
q.push(0);
cost[0]=0;
over[0]=1;
int vis[205]={0}; //这步千万别忘啊!!
int costs=100000000,happys=-1,nums=100000000,p;
while(!q.empty()){
int fr=q.top();
q.pop();
if(vis[fr]==1) continue; //这步千万别忘啊!!
vis[fr]=1; //这步千万别忘啊!!
if(fr==ed){
if(cost[fr]<costs||
(cost[fr]==costs&&happy[fr]>happys)||
(cost[fr]==costs&&happy[fr]==happys&&num[fr]<nums)){
costs=cost[fr];
happys=happy[fr];
nums=num[fr];
p=fr;
}
continue;
}
for(int i=0;i<n;++i){
if(vis[i]==1) continue; //这步千万别忘啊!!
if(cost[fr]+w[fr][i]<=cost[i]){
if(cost[fr]+w[fr][i]<cost[i]||
(cost[fr]+w[fr][i]==cost[i]&&happy[fr]+x[i].b>happy[i])||
(cost[fr]+w[fr][i]==cost[i]&&happy[fr]+x[i].b==happy[i]&&num[fr]+1<num[i])){
happy[i]=happy[fr]+x[i].b;
num[i]=num[fr]+1;
path[i]=fr;
}
if(cost[i]==cost[fr]+w[fr][i]){
over[i]+=over[fr];
}
else{
q.push(i);
over[i]=over[fr];
cost[i]=cost[fr]+w[fr][i];
}
}
}
}
cout<<over[ed]<<" "<<costs<<" "<<happys<<" "<<happys/nums<<endl;
stack<int> st;
st.push(ed);
while(ed!=0){
ed=path[ed];
st.push(ed);
}
while(!st.empty()){
cout<<x[st.top()].a;
st.pop();
if(st.empty())
cout<<endl;
else
cout<<"->";
}
}
总结一下:考PAT还是别写什么复杂的优先队列还是前向星了,节省时间增加正确率才是王道!
另外,PAT的最短路做来做去感觉好像都差不多。比如:
https://www.patest.cn/contests/pat-a-practise/1111
#include<bits/stdc++.h>
using namespace std;
struct node{
int a,b;
}x[505][505];
int dis[505];
int spd[505];
int vis[505];
int path[505];
int path2[505];
int n,m,a,b,c,d,e,st,ed;
int main(){
cin>>n>>m;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
x[i][j].a=x[i][j].b=100000000;
}
}
while(m--){
cin>>a>>b>>c>>d>>e;
if(c==1)
x[a][b]={d,e};
else{
x[a][b]={d,e};
x[b][a]={d,e};
}
}
cin>>st>>ed;
int tmp=ed;
for(int i=0;i<n;++i){
dis[i]=100000000;
spd[i]=100000000;
}
dis[st]=0;spd[st]=0;
for(int nn=0;nn<n;++nn){
int minn=100000000,minn2=100000000,p=-1;
for(int i=0;i<n;++i){
if(((dis[i]<minn)||
(dis[i]==minn&&spd[i]<minn2))&&vis[i]==0){
minn=dis[i];
minn2=spd[i];
p=i;
}
}
vis[p]=1;
if(p==ed)
break;
for(int i=0;i<n;++i){
if(vis[i]==1) continue;
if(dis[p]+x[p][i].a<dis[i]||
(dis[p]+x[p][i].a==dis[i]&&spd[p]+x[p][i].b<spd[i])){
dis[i]=dis[p]+x[p][i].a;
spd[i]=spd[p]+x[p][i].b;
path[i]=p;
}
}
}
int ans=dis[ed];
for(int i=0;i<n;++i){
dis[i]=100000000;
spd[i]=100000000;
}
ed=tmp;
dis[st]=0;spd[st]=0;
memset(vis,0,sizeof(vis));
for(int nn=0;nn<n;++nn){
int minn=100000000,minn2=100000000,p=-1;
for(int i=0;i<n;++i){
if(((spd[i]<minn)||
(spd[i]==minn&&dis[i]<minn2))&&vis[i]==0){
minn=spd[i];
minn2=dis[i];
p=i;
}
}
vis[p]=1;
if(p==ed)
break;
for(int i=0;i<n;++i){
if(vis[i]==1) continue;
if(spd[p]+x[p][i].b<spd[i]||
(spd[p]+x[p][i].b==spd[i]&&dis[p]+1<dis[i])){
spd[i]=spd[p]+x[p][i].b;
dis[i]=dis[p]+1;
path2[i]=p;
}
}
}
int u=0;
while(ed!=st){
if(path[ed]!=path2[ed]){
u=1;
break;
}
ed=path[ed];
}
ed=tmp;
stack<int> stk;
if(u==0){
cout<<"Distance = "<<ans<<"; Time = "<<spd[ed]<<": ";
stk.push(ed);
while(ed!=st){
ed=path[ed];
stk.push(ed);
}
while(!stk.empty()){
cout<<stk.top();
stk.pop();
if(!stk.empty())
cout<<" -> ";
else
cout<<endl;
}
return 0;
}
cout<<"Distance = "<<ans<<": ";
stk.push(ed);
while(ed!=st){
ed=path[ed];
stk.push(ed);
}
while(!stk.empty()){
cout<<stk.top();
stk.pop();
if(!stk.empty())
cout<<" -> ";
else
cout<<endl;
}
ed=tmp;
cout<<"Time = "<<spd[ed]<<": ";
stk.push(ed);
while(ed!=st){
ed=path2[ed];
stk.push(ed);
}
while(!stk.empty()){
cout<<stk.top();
stk.pop();
if(!stk.empty())
cout<<" -> ";
else
cout<<endl;
}
}
再比如:
https://www.patest.cn/contests/gplt/L2-001
#include<bits/stdc++.h>
#define ll long long
using namespace std; //
struct EDGE{
int u,v,w,next;
}edge[500*500*2+5];
int head[500*500+5],pp;
void init(){
pp=0;
memset(head,0,sizeof(head));
}
void add(int u,int v,int w){
edge[++pp]=(EDGE){u,v,w,head[u]};
head[u]=pp;
}
int n,m,a,b,c,d,e;
int x[505];
int vis[505];
int dis[505];
int cost[505];
int path[505];
int times[505];
struct cmp{
bool operator()(const int &t1,const int &t2){
if(dis[t1]!=dis[t2])
return dis[t1]>dis[t2];
return cost[t1]<cost[t2];
}
};
int main(){
cin>>n>>m>>a>>b;
init();
for(int i=0;i<n;++i)
cin>>x[i];
while(m--){
cin>>c>>d>>e;
add(c,d,e);
add(d,c,e);
}
for(int i=0;i<n;++i)
dis[i]=100000000;
priority_queue<int,vector<int>,cmp> q;
q.push(a);
dis[a]=0;
cost[a]=x[a];
times[a]=1;
while(!q.empty()){
int u=q.top();
q.pop();
if(vis[u]==1) continue;
vis[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
int w=edge[i].w;
if(vis[v]==1) continue;
if(dis[u]+w<dis[v]) times[v]=times[u];
else if(dis[u]+w==dis[v]) times[v]+=times[u];
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
cost[v]=cost[u]+x[v];
q.push(v);
path[v]=u;
}
else if(dis[u]+w==dis[v]&&cost[u]+x[v]>cost[v]){
cost[v]=cost[u]+x[v];
q.push(v);
path[v]=u;
}
}
}
cout<<times[b]<<" "<<cost[b]<<endl;
stack<int> st;
int tmp=b;
while(path[b]!=a){
st.push(path[b]);
b=path[b];
}
cout<<a;
while(!st.empty()){
cout<<" "<<st.top();
st.pop();
}
if(b!=a)
cout<<" "<<tmp;
cout<<endl;
}
如果九月份再出这种类型的压轴题就完全可以pass了……