人总要摸着石头过河~错误都是难得的经验
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int sr,endd,w[510],tempw=0,maxt=0,a[510][510],cnt=0,dsr[510],visit[510]={0};//w0-n w[0]=1
const int inf=1000000000;
vector<int> pre[510],tempath;
/*void dfs(int fin){
tempw+=w[fin];
if(fin==sr){
if(tempw>maxt){
maxt=tempw;
tempw=tempw-w[sr];//因为此时下一次递归只出去了最后一个前面的都要保留(注意)
//return 位置弄错导致cnt没记上去
}
cnt++;
return;
}
for(int i=0;i<pre[fin].size();i++){
dfs(pre[fin][i]);//完成之后退回来会直接加下一个孩子所以源点end的值没加
}
} */
void dfs(int f){
//END
if(f==sr){
tempath.push_back(sr);
tempw=0;//条件重置不能前面影响后面
for(int j=tempath.size()-1;j>=0;j--){
tempw+=w[tempath[j]]; //加的应该是tempath里面的索引号各种路径终不能是递减的 双索引的情况(注意)
}
if(tempw>maxt){
maxt=tempw;
//若有path还要更新path path=tempath
}
cnt++;
tempath.pop_back();
return;//return一定要放到最后
}
tempath.push_back(f);
for(int i=0;i<pre[f].size();i++){
dfs(pre[f][i]);
}
tempath.pop_back();
}
int main(){
int n,m,ttw,_1,_2,_3;
cin>>n>>m>>sr>>endd;
fill(dsr,dsr+510,inf);
fill(a[0],a[0]+510*510,inf);
for(int i=0;i<n;i++){
cin>>ttw;
w[i]=ttw;
}
for(int i=0;i<m;i++){
cin>>_1>>_2>>_3;
a[_1][_2]=a[_2][_1]=_3;
}
dsr[sr]=0;
for(int i=0;i<n;i++){
int u=-1,minn=inf;
for(int j=0;j<n;j++){
if(visit[j]==0&&dsr[j]<minn){
minn=dsr[j];
u=j;
}
}
if(u==-1) break;
visit[u]=1;
for(int v=0;v<n;v++){
if(visit[v]==0&&a[u][v]!=inf){
if(dsr[v]>a[u][v]+dsr[u]){
dsr[v]=a[u][v]+dsr[u];
pre[v].clear();
pre[v].push_back(u);
}
else if(dsr[v]==a[u][v]+dsr[u]){//择一 dijsktra最重要的部分掉了个else导致整个出错,else不带pre数组就会出错(注意)
pre[v].push_back(u);
}
}
}
}
/*for(int i=1;i<=4;i++){
for(int j=0;j<pre[i].size();j++){
printf("%d ",pre[i][j]);
}
printf("\n");
} //起点没有前驱(注意) */
dfs(endd);
printf("%d %d",cnt,maxt);
return 0;
}
搞了三个小时吧,期间对dijkstra易错点基本上都弄了一遍实属不易~长话短说
第一遍:没有存储路径,懒吗企图省点力气就在dfs内做了很大的简化,见我注释掉的
确实可以算一条路径的准确权重 但是!!当完成一条后应该弹出一个进行下面的 我直接将temp弄成0天真的以为他能再重新加一遍错了,此时他只会在我弄得0的基础上如果下一个点是最终点只会再加哪一个结束当然错误
反例
4 5 0 3
1 4 1 2
0 1 1
0 2 2
0 3 4
1 2 1
2 3 2
正确答案
3 8
为啥呢
前序数组 注意起点0没有前序
1 :0
2 :0 1
3 :0 2
路径
3->0
3->2->0
3->2->1->0
如果你直接令temp=0or temp=w[end]的话在前序数组中2 遍历完0后会紧接着取遍历1此时temp里面除了有 end 的值还有2的值所以还是不对
第二遍 temp改为 temp=temp-w[sr] 就是减去弹出的的点的值这总行了吧 里面有了出去弹出去的所有的值 不好意思~还有反例
前序数组 注意起点0没有前序
2 :0
3 :2 0
对前序数组稍作修改
3->2->0
3->0
此时3遍历2,2遍历0到了终点去掉0的值,里面有3,2的值再去遍历0,还是3,2,0,的值本来是3->0,里面只有3,0的值又多了一个
所以用路径存储是正确的temp面对的情况太多不好直接赋值
这两个反例也是为什么 路径存储中为什么那两个pop_back()放在那里的原因,放在return 上面的,是为了解决第一种情况只去源点的情况,放在dfs下面的是为了解决第二个反例,就是源点去了,恰好这一路也结束的情况,要把没用的2 pop_back
通过这两个反例理解了为什么pop_back()的位置放在那里
dijkstra+dfs易错点
1.里面最后一个for循环如果有多种情况,一定要写if else if ....不能把else弄掉否则第一个if改了条件直接导致第二个if成立就错了
2.不管如何在dfs中必须存储路径,来计算其他性质
3.dfs中 return,应该放在所有该干的事下面不能放在要求的性质的上面
4.注意算性质处的双重索引的情况w[tempath[j]],始终要写路径中的索引别漏写,对于这种判断编写的时候就要带入几个判断一下,避免出错
5.注意求和路径中权值和要条件重置sum=0