总结:这场比赛主要是得写出F题才能跨层。五题看罚时。以后能用next_permutation就不要用dfs,dfs写得比较长,浪费时间。然后B那题String,用stack模拟即可,不用想其他离奇的实现,又是浪费时间。
Problem - F - Codeforces-Photography
题意:在5000个带权点,5000条边的无向图中,找连续,且能无折返遍历的,且最多可以选5个点,找到最大的权重之和。
思路:一个很好的预处理思想:一条路径上共 5 个点,枚举 2 3 4 这三个点,1 和 5 一定取 2 和 4 出边前四大的。
//网络寻路:https://www.luogu.com.cn/problem/P8605
//一个很好的预处理思想:一条路径上共 5 个点,枚举 2 3 4 这三个点,1 和 5 一定取 2 和 4 出边前四大的。
typedef struct node{
int a,b,c;
}node;
int n,m;
int arr[5005];
vector<pair<int,int>> vct[5005];
vector<node> v3; 直接用vector存(200+ms),存了重复边也不会MLE,也不会TLE,比用set去重(2000+ms)之后跑到快的多的多的多。。
void dfs(int s,node x){ 预处理所有三个点
if(x.c!=-1){
v3.emplace_back(x);
return;
}
if(x.b==-1){
for(auto v:vct[s]){
int to=v.second;
if(to!=x.a){
x.b=to;
dfs(x.b,x);
}
}
}
else if(x.c==-1){
for(auto v:vct[s]){
int to=v.second;
if(to!=x.a&&to!=x.b){
x.c=to;
dfs(x.c,x);
}
}
}
}
void solve(){ F Photography 这是第二版代码,加上n=2特判,不开longlong即可完美ac....
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>arr[i];
int ans=0;
for(int i=1;i<=m;i++){
int u,v; cin>>u>>v;
vct[u].emplace_back(arr[v],v);
vct[v].emplace_back(arr[u],u);
ans=max(ans,arr[v]+arr[u]); n=2的情况!!
}
for(int i=1;i<=n;i++) {
node x; x.a=i,x.b=-1,x.c=-1;
dfs(i,x);
sort(vct[i].begin(),vct[i].end(),greater<pair<int,int>>()); 按照权重,从大到小排序。
}
// for(int i=1;i<=n;i++){ 代替dfs预处理三个点
// sort(vct[i].begin(),vct[i].end(),greater<pair<int,int>>());
// node x; x.a=i;
// for(auto v1:vct[i]){
// x.b=v1.second;
// for(auto v2:vct[v1.second]){
// if(v2.second!=i){
// x.c=v2.second;
// v3.emplace_back(x);
// }
// }
// }
// }
for(auto s:v3){
int l=s.a,m=s.b,r=s.c,nex1=-1,nex11=-1,nex2=-1,nex22=-1,res=arr[l]+arr[m]+arr[r];
for(auto v:vct[l]){
int to=v.second;
if(to==l) continue;
if(nex1==-1&&to!=m&&to!=r) nex1=to;
else if(to!=m&&to!=r&&to!=nex1){
nex11=to;
break;
}
}
for(auto v:vct[r]){
int to=v.second;
if(to==r) continue;
if(nex2==-1&&to!=l&&to!=m) nex2=to;
else if(to!=l&&to!=m&&to!=nex1&&to!=nex2){
nex22=to;
break;
}
}
if(nex1!=-1&&nex2!=-1){ 这是第二版代码 这里的if判断更强。
if(nex1!=nex2) res+=arr[nex1],res+=arr[nex2];
else if(nex11!=-1&&nex22!=-1){
if(arr[nex11]>=arr[nex22]) res+=arr[nex2],res+=arr[nex11];
else if(arr[nex22]>arr[nex11]) res+=arr[nex1],res+=arr[nex22];
}
else if(nex11!=-1) res+=arr[nex2],res+=arr[nex11];
else if(nex22!=-1) res+=arr[nex1],res+=arr[nex22];
else res+=arr[nex1];
}
else if(nex1!=-1) res+=arr[nex1];
else if(nex2!=-1) res+=arr[nex2];
ans=max(ans,res);
}
cout<<ans;
}
这个代码比用set存预处理跑的快的多
要注意的点:注意n=2,的情况,还有千万不能开long long!开long long会导致TLE30 或 MLE30.