1 条题解

  • 0
    @ 2026-5-12 18:57:06

    思路

    1.若询问中的两点不在同一个联通块中,输出nannan

    2.若两点的连通块存在正环或负环,则输出infinf。可能有人会问:为啥负环也行?如果说你反着走负环,他不就是一个正环了嘛?

    3.除了正环和负环,还有什么环?对了,边权和为00的环。如果有一个边权为00的环,我说它上面的任意两点的两种路径距离相同。证明如下:
    设点xx到点yy两种路径的长度分别为aabb,则从yyxx的第二条路径长度为b-b,由于这两条(xxyyyyxx)构成一个边权和为00的环,则有a+(b)=0a+(-b)=0,则有a=ba=b

    4.综上所述,若两点之间的连通块不存在正环和负环,必然任何路径长度都相等。

    那又如何找答案呢?

    对于任意一个连通块,随意定义一个点stst为起始点,遍历其每一个点,记录下路径长度,顺便判断一下正负环。若询问xxyy的距离,则距离为disy,stdisx,stdis_{y,st}-dis{x,st},翻译成人话就是从xxstst再到yy

    又有人问了:那这如果不是最优路径咋办?

    你是不是忘了,若没有正负环,两点之间的任意路径长度都相同。

    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
    上传者