1 条题解

  • 0
    @ 2025-10-10 19:32:49

    C++ :

    #include <bits/stdc++.h>
    using namespace std;
    
    /*
    1.本题相当于问:1~ai,是否存在长度为li的路径;
      路线可以折回走(来回走)
    2.判断方法:
    假设路径长度L>0,那么任选一条边来回走。
    走1次:L+2,走2次:L+4...
    结论:有一条长度是L的路径,一定可以构造出和L奇偶性和L相同的路径(L>0) 
    
    假设L是奇数。
    存在长度是L的奇数路径,相当于:L>=长度是奇数的最短路。
    
    因此,需要求:1~a中长度是奇数的最短路 和 长度为偶数的最短路。 
    */
    
    /*
    dis[v][1] 表示1号点到达v的最短奇数路径
    dis[v][0] 表示1号点到达v的最短偶数路径 
    dis[v][0] = min(dis[v][0],dis[u][1]+1)
    dis[v][1] = min(dis[v][1],dis[u][0]+1)
    1号点到1号点的最短偶数路径为0
    1号点到1号点的最短奇数路径为不存在,设置为无穷大 
    */
    
    const int MAXN = 1e5+10;
    
    //采用链式前向星的方式来存储图(边)
    struct Edge{
    	//从u出发,到v去,next表示从u出发的上一条边在edge数组的哪个位置 
    	int u,v,next;
    }; 
    //无向图的方向是双向的,因此边要开2倍的空间
    Edge edge[MAXN * 2];
    
    int pre[MAXN]; //存储每个顶点的第一条边的起始位置
    int dis[MAXN][2];//存储1到每个点的最短路径
    int que[MAXN * 10],q2[MAXN*10];//出队的元素可能再入队,队列要大一些
    int vis[MAXN][2];//标记点是否在队列中 
    int k=1,n,m,q,head,tail;
    
    //追加边:链式前向星存储 
    void add(int from,int to){
    	edge[k].u = from;
    	edge[k].v = to;
    	edge[k].next = pre[from];//前一条边的下标,形成边的链表
    	pre[from] = k;//更新u的上一条边的序号
    	k++; 
    } 
    
    //spfa:求最短路
    void spfa(){
    	//初始化dis数组:1号顶点到其它顶点奇偶最短路径 
    	for(int i = 1;i <= n;i++){
    		dis[i][0] = 1e9;
    		dis[i][1] = 1e9;
    	} 
    	
    	dis[1][0] = 0;//1号顶点到1号顶点的偶数最短路
    	
    	que[++tail] = 1;
    	while(head != tail){
    		int u = que[head+1];
    		
    		for(int i = pre[u];i != 0;i = edge[i].next){
    			int v = edge[i].v;
    			
    			//更新1号顶点到v顶点的偶数最短路 
    			if(dis[v][0] > dis[u][1] + 1){
    				dis[v][0] = dis[u][1] + 1;
    				//如果没有标记 
    				if(!vis[v][0]) {
    					que[++tail] = v;//入队
    					q2[++tail] = 0;//奇偶性入队
    					vis[v][0] = 1;//标记在队列中 
    				}
    			}
    			
    			//更新1号顶点到v顶点的奇数最短路 
    			if(dis[v][1] > dis[u][0] + 1){
    				dis[v][1] = dis[u][0] + 1;
    				//如果没有标记 
    				if(!vis[v][1]) {
    					que[++tail] = v;//入队
    					q2[++tail] = 1;//奇偶性入队
    					vis[v][1] = 1;//标记在队列中 
    				}
    			}
    		}
    		
    		int r = q2[head+1];
    		vis[u][r] = 0;//奇偶性出队
    		
    		head++; //看下一个点 
    	} 
    } 
    
    int main(){
    	cin>>n>>m>>q;
    	int u,v;
    	for(int i = 1;i <= m;i++){
    		cin>>u>>v;
    		add(u,v);//无向图,两个方向都要存 
    		add(v,u); 
    	} 
    	
    	//求最短路
    	spfa();
    	
    	//判断特殊情况:1号点是独立的 
    	if(pre[1] == 0) dis[1][0] = 1e9; 
    	
    	//q次询问
    	int l;
    	for(int i = 1;i <= q;i++){
    		cin>>u>>l;
    		//如果l是偶数,且l>=dis[u][0]
    		//或者l是奇数,且l>=dis[u][1] 
    		if(l>=dis[u][l%2]) cout<<"Yes"<<endl;
    		else cout<<"No"<<endl;
    	} 
    	
    	return 0;
    }
    
    
    
    • 1

    信息

    ID
    906
    时间
    1000ms
    内存
    512MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者