来源:Luogu P2966,JZOJ #318
题目描述
凯凯的工厂正在有条不紊地生产一种神奇的零件,神奇的零件的生产过程自然也很神奇。工厂里有 位工人,工人们从 编号。某些工人之间存在双向的零件传送带。保证每两名工人之间最多只存在一条传送带。
如果 号工人想生产一个被加工到第 阶段的零件,则所有与 号工人有传送带直接相连的工人,都需要生产一个被加工到第 阶段的零件(但 号工人自己无需生产第 阶段的零件)。
如果 号工人想生产一个被加工到第 阶段的零件,则所有与 号工人有传送带直接相连的工人,都需要为 号工人提供一个原材料。
轩轩是 号工人。现在给出 张工单,第 张工单表示编号为 的工人想生产一个第 阶段的零件。轩轩想知道对于每张工单,他是否需要给别人提供原材料。他知道聪明的你一定可以帮他计算出来!
解题思路
- 我们想象 号点到 号点有一条长度为 的路径
- 因为L>0 ,而且可以在路径中选一条边来回走
- 所以就可以构造 L+2 L+4 L+6 ……
- 因此只要有一条长度是L的路径,那么就能构造出所有长度大于等于L,而且奇偶性相同的路径。
- 假设L为奇数或偶数
- 如果要求出 一条长度为L的路径,也就是说必须有一条长度为奇数的路径。
- (如果要求出 一条长度为L的路径,也就是说必须有一条长度为偶数的路径。)
我们就求出从1到i 的长度为奇数的最短路 ,
题目求是否存在一条长度为L的路径其实等于 - L是偶数
-
到
有一条边
代码君
#include <bits/stdc++.h>
using namespace std;
const int MAXN=100000*2+10;
int t=0,n,m,q;
int dis_e[MAXN],dis_o[MAXN],linkk[MAXN],Q[MAXN],vis[MAXN];
struct node
{
int y,next;
}e[MAXN];
void insert(int x,int y)
{
e[++t].y=y;
e[t].next=linkk[x]; linkk[x]=t;
}
void SPFA(int st) //SPFA
{
memset(dis_e,10,sizeof(dis_e));
memset(dis_o,10,sizeof(dis_o));
memset(vis,0,sizeof(vis));
dis_e[st]=0; vis[st]=1;
int head=1,tail=1;
Q[head]=st;
for (head=1;head<=tail;head++)
{
int x=Q[head]; //取出队头
for (int i=linkk[x];i>0;i=e[i].next) //邻接表查询
{
int y=e[i].y;
if (dis_e[x]+1<dis_o[y] || dis_o[x]+1<dis_e[y])
{
dis_o[y]=min(dis_o[y],dis_e[x]+1); //更新最优解
dis_e[y]=min(dis_e[y],dis_o[x]+1);
Q[++tail]=y; //入队
vis[y]=1;
}
}
vis[x]=0; //出队
}
}
int main()
{
freopen("work.in","r",stdin);
freopen("work.out","w",stdout);
scanf("%d %d %d",&n,&m,&q);
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d %d",&x,&y);
insert(x,y); //邻接表存储
insert(y,x);
}
SPFA(1);
for (int i=1;i<=q;i++) //q次询问
{
int a,L;
scanf("%d %d",&a,&L);
if (L%2==1 && L>=dis_o[a] || L%2==0 && L>=dis_e[a]) //判断是否可行
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}