1 条题解
-
0
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
- 上传者