[Usaco2010 Feb]Chocolate Giving 最短路dijkstra+堆优化
本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
题目:传送门
最短路板子题:迪杰斯特拉+堆优化
注意:因为我建的是大根堆,所以要将距离取负,再存入大根堆堆中,这样队首就是最小值。
dijkstra与SPFA还有一个区别是dijkstra的标记数组时根节点不能先标记访问过,否则到后面直接会把根节点continue;距离直接为初始化的最大值,不会遍历树了。
直接套模板即可
code:
1 #include<bits/stdc++.h> 2 #define inf 0x3f3f3f3f 3 #pragma GCC optimize(3) 4 const int N=50005; 5 const int M=200002; 6 using namespace std; 7 int n,m,B; 8 int tot; 9 int ver[M],nxt[M],head[N],edge[M]; 10 int dis[N]; 11 int opt,ch; 12 bool flag[N]; 13 priority_queue< pair<int,int> >q;//第一个是距离,第二个是节点编号 14 inline int read(){ 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 17 while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 18 return x*f; 19 } 20 inline void write(int x) 21 { 22 if(x<0)x=-x,putchar('-'); 23 if(x>9)write(x/10); 24 putchar(x%10+'0'); 25 } 26 void add(int x,int y,int z){ 27 ++tot; 28 ver[tot]=y; 29 edge[tot]=z; 30 nxt[tot]=head[x]; 31 head[x]=tot; 32 } 33 void dij(){ 34 // memset(dis,0x3f,sizeof(dis)); 35 // memset(flag,0,sizeof(flag)); 36 for(int i=1;i<=n;i++){ 37 dis[i]=inf;//因为求最短距离,所以距离初始最大 38 flag[i]=0;//所有点最开始都没有访问 39 }//初始化 40 dis[1]=0;//以1为根的点初始距离为0 41 q.push(make_pair(0,1));//以1为根的初始距离0入队,节点编号1也入队 注意:flag[1]不能标记为true 42 while(q.size()){//当堆不为空时,才能访问 43 int x=q.top().second;//x为队首节点编号 44 q.pop();//取出x 45 if(flag[x])continue;//如果x先前已经访问过了,就不需要继续访问了 46 flag[x]=true;//否则就访问x,并把x打上已访问的标记 47 for(int i=head[x];i;i=nxt[i]){ 48 int y=ver[i],z=edge[i]; 49 if(dis[y]>dis[x]+z){//若根节点到y的距离大于到x的距离+当前的距离 50 dis[y]=dis[x]+z;//更新,求最小值 51 q.push(make_pair(-dis[y],y));//入堆 52 } 53 } 54 } 55 } 56 int main() 57 { 58 n=read(),m=read(),B=read(); 59 for(int i=1,x,y,z;i<=m;i++){ 60 x=read(),y=read(),z=read(); 61 add(x,y,z); 62 add(y,x,z); 63 } 64 dij(); 65 while(B--){ 66 ch=read(),opt=read(); 67 printf("%d\n",dis[ch]+dis[opt]);//依据题意 68 } 69 return 0; 70 }