加工零件(奇偶最短路)

加工零件:https://www.luogu.com.cn/problem/P5663

一下解释部分借鉴 fdszlzldalao

观察发现,由于1->2的路径长度为1,只要点2的阶段为奇数,则点1一定要提供原材料(1->2->1->2->...)

观察发现,由于1->2->3的路径长度为2,只要点3的阶段为偶数,则点1一定要提供原材料

从1到v,路径很多,长度不尽相同。如果1到v的路径长度存在4时,v在阶段4、6、8、10…时,1肯定可以为0。当v的路径长度存在3时,v在3、5、7、9…阶段,1肯定可以为0。

因此要求的就是1到v的最短奇数路径和最短偶数路径。

若v的阶段为偶数x,存在v的最短偶数路径y,满足x>=y,1即可为0。

若v的阶段为奇数x,存在v的最短奇数路径y,满足x>=y,1即可为0。

设dis[v][0]为1到v的最短偶数路径,设dis[v][1]为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,dis[1][0]显然等于0,dis[1][1]显然不可能,设为无穷大。

#include <bits/stdc++.h>
using namespace std;
const int maxn=200009;
int head[maxn],dis[maxn][2],n,m,cnt=1,vis[100009],s,l,r;
struct p{
    int x,num;
    bool operator < (const p&tmp)    const{
        return x>tmp.x;
    }
};
priority_queue<p>q;
struct node{
    int to,nxt,w;
}d[maxn];
void add(int u,int v,int w){
    d[cnt].to=v,d[cnt].w=w,
    d[cnt].nxt=head[u],head[u]=cnt++;    
}
void ji(int z,int k){
    p t;t.num=k,t.x=z;
    if(z%2==1&&dis[k][1]>z)
    {
        dis[k][1]=z;
        q.push(t);
    }
    if(z%2==0&&dis[k][0]>z)
    {
        dis[k][0]=z;
        q.push(t);
    }
}
void dij()
{
    memset(dis,20,sizeof(dis));
    dis[1][0]=0;p init;//起始偶数为0 
    init.num=1,init.x=0;q.push(init);
    while(!q.empty())
    {
        p ans=q.top();q.pop();
        if(vis[ans.num])    continue;
        vis[ans.num]=0;
        for(int i=head[ans.num];i;i=d[i].nxt)
        {
            int z=dis[ans.num][0]+d[i].w;
            ji(z,d[i].to);
            z=dis[ans.num][1]+d[i].w;
            ji(z,d[i].to);
        }
    }
}
int main()
{
    cin>>n>>m>>s;
    for(int i=1;i<=m;i++)
    {
        cin>>l>>r;
        add(l,r,1);add(r,l,1);
    }
    dij();
    for(int i=1;i<=s;i++)
    {
        cin>>l>>r;
        if(r%2==1&&dis[l][1]<=r)    cout<<"Yes";
        else if(r%2==0&&dis[l][0]<=r)    cout<<"Yes";
        else    cout<<"No";
        cout<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/iss-ue/p/12460495.html