1 条题解
-
0
思路
1.若询问中的两点不在同一个联通块中,输出。
2.若两点的连通块存在正环或负环,则输出。可能有人会问:为啥负环也行?如果说你反着走负环,他不就是一个正环了嘛?
3.除了正环和负环,还有什么环?对了,边权和为的环。如果有一个边权为的环,我说它上面的任意两点的两种路径距离相同。证明如下:
设点到点两种路径的长度分别为和,则从到的第二条路径长度为,由于这两条(到和到)构成一个边权和为的环,则有,则有4.综上所述,若两点之间的连通块不存在正环和负环,必然任何路径长度都相等。
那又如何找答案呢?
对于任意一个连通块,随意定义一个点为起始点,遍历其每一个点,记录下路径长度,顺便判断一下正负环。若询问到的距离,则距离为,翻译成人话就是从到再到。
又有人问了:那这如果不是最优路径咋办?
你是不是忘了,若没有正负环,两点之间的任意路径长度都相同。
AC 代码
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e5+10; int n,m,q,cid,vis[N],dis[N],bad[N],co[N]; vector<pair<int,int>>G[N]; void dfs(int x) { co[x]=cid; for(auto i:G[x]) { int y=i.first,w=i.second; if(!vis[y])dis[y]=dis[x]+w,vis[y]=1,dfs(y); else if(dis[y]!=dis[x]+w)bad[cid]=1; } } signed main() { scanf("%lld%lld%lld",&n,&m,&q); for(int i=1,x,y,w;i<=m;i++) { scanf("%lld%lld%lld",&x,&y,&w); G[x].push_back({y,w}); G[y].push_back({x,-w}); } for(int i=1;i<=n;i++)if(!vis[i])cid++,vis[i]=1,dfs(i); while(q--) { int x,y;scanf("%lld%lld",&x,&y); if(co[x]!=co[y])puts("nan"); else if(bad[co[x]])puts("inf"); else printf("%lld\n",dis[y]-dis[x]); } return 0; }PS:谢谢QWEN大大写的代码
- 1
信息
- ID
- 713
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 4
- 上传者