解释下这段代码 #include<cstdio> #include<queue> using namespace std; #define int long long const int MAXN=400+5,MAXM=2e5+5,INF=0x3f3f3f3f3f3f3f3f; int n,m; int su,en[MAXM],lt[MAXM],hd[MAXN]; int dis[MAXN]; bool viz[MAXM],vis[MAXN]; int nxt[MAXN][2]; bool isok[MAXM]; struct node{ int ix,vl; bool operator>(const node &t)const { if(vl!=t.vl) return vl>t.vl; return ix<t.ix; } }; inline int rd() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return x*f; } void write(int x) { if(x<0){putchar('-'),write(-x);return;} if(x>9) write(x/10),putchar(x%10+48); else putchar(x+48); } inline void add(int u,int v) { en[++su]=v,lt[su]=hd[u],hd[u]=su; } inline int Dij(int x) { priority_queue<node,vector<node>,greater<node>> q; for(int i=1;i<=m;++i) viz[i]=(i==x)?1:0; for(int i=1;i<=n;++i) vis[i]=0,dis[i]=INF; q.push({1,0}); vis[1]=1; dis[1]=0; while(!q.empty()) { int u=q.top().ix;q.pop(); for(int i=hd[u];i;i=lt[i]) { if(viz[i]) continue; int v=en[i]; if(dis[v]>dis[u]+1) { nxt[v][0]=u,nxt[v][1]=i; dis[v]=dis[u]+1; if(!vis[v]) vis[v]=1,q.push({v,dis[v]}); } } } return dis[n]; } signed main() { n=rd(),m=rd(); for(int i=1;i<=m;++i) { int u=rd(),v=rd(); add(u,v); } int Max=Dij(0); Max=(Max==INF)?-1:Max; int tmp=n; while(tmp!=0) { isok[nxt[tmp][1]]=1; tmp=nxt[tmp][0]; } for(int x=1,ans;x<=m;++x) { if(isok[x]) { ans=Dij(x); if(ans==INF) ans=-1; } else ans=Max; write(ans),putchar('\n'); } return 0; }
时间: 2024-04-08 07:32:21 浏览: 131
这段代码是一个求解图中所有点到起点的最短路径的程序。让我来逐段解释它的功能。
首先,代码包含了两个头文件 `<cstdio>` 和 `<queue>`,分别用于输入输出和队列操作。
接下来,使用 `using namespace std;` 命名空间声明来简化使用标准库函数和对象。
然后,定义了一些常量和变量。其中,`MAXN` 和 `MAXM` 分别表示最大的点数和边数,`INF` 表示一个足够大的值,`n` 和 `m` 分别表示点的个数和边的个数。`su` 表示边的编号,`en` 和 `lt` 分别表示边的终点和链表头指针,`hd` 表示头结点指针,`dis` 表示最短路径数组,`viz` 和 `vis` 分别表示边和点的访问标记,`nxt` 表示下一个点和边的指针,`isok` 表示边是否在最短路径上。另外,还定义了一个结构体 `node` 用于存储点和对应的最短路径值,重载了 `>` 运算符用于优先队列的比较。
接着,定义了一个读入整数的函数 `rd()` 和一个输出整数的函数 `write()`,用于方便的输入输出。
然后,定义了一个添加边的函数 `add()`,用于构建图。
接下来,定义了一个 Dijkstra 算法的函数 `Dij()`,用于计算点到起点的最短路径。在函数内部,使用优先队列 `q` 存储点和对应的最短路径值,初始化点和路径值数组。然后,将起点入队,并标记为已访问。之后,不断从队列中取出最小路径值的点,遍历其相邻的边,更新最短路径值和下一个点的指针,并将下一个点入队。最后,返回终点的最短路径值。
接着,主函数 `main()` 开始执行。首先从输入读取点和边的个数,并使用 `add()` 函数构建图。
然后,调用 `Dij()` 函数计算起点到终点的最短路径,并将结果赋值给变量 `Max`,若结果为 `INF` 则置为 `-1`。
接下来,根据最短路径的下一个点指针构建最短路径上的边。
然后,从1到边的个数循环遍历每条边。如果边在最短路径上,则调用 `Dij()` 函数计算以该边为起点的最短路径,并将结果赋值给变量 `ans`。如果结果为 `INF` 则置为 `-1`。最后,调用 `write()` 函数输出结果。
最后,主函数返回0,程序结束。
阅读全文