11.3清北集訓最短路奇偶拆點
阿新 • • 發佈:2018-11-08
solution
- 顯然假如詢問u->v,w為奇數,如果u->v的奇數最短路<=w,那麼這組詢問一定是yes,偶數與之相同
- 所以我們只要求出任意u->v的奇數偶數最短路即可
- 如何??
- 我們考慮u->v的一條邊我們把它拆成u->v+n和u+n->v的兩條邊
- u到v的最短路就拆成了u->v(偶數)和u->v+n(奇數)兩種.
code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #include<cstdlib> #include<ctime> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; inline int read(){ char ch=' ';int f=1;int x=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } const int N=2200; const int M=10100; struct node { int v,nxt; }edge[M<<1]; int head[N],cnt; void add(int u,int v) { cnt++; edge[cnt].v=v; edge[cnt].nxt=head[u]; head[u]=cnt; } int dis[N][N]; int q[N],h,t; bool a[N]; int n; void bfs(int s) { for(int i=1;i<=n*2;i++) dis[s][i]=-1; if(a[s]) return ; h=1;t=0;q[++t]=s;dis[s][s]=0; while(h<=t) { int u=q[h++]; for(int i=head[u];i;i=edge[i].nxt) { int v=edge[i].v; if(dis[s][v]==-1) { dis[s][v]=dis[s][u]+1; q[++t]=v; } } } } int main() { freopen("chase.in","r",stdin); freopen("chase.out","w",stdout); int m; n=read();m=read(); int i,j;int x,y,k; for(i=1;i<=n;i++) a[i]=true; for(i=1;i<=m;i++) { x=read();y=read(); add(x,y+n);add(x+n,y); add(y+n,x);add(y,x+n); a[x]=a[y]=false; } for(i=1;i<=n;i++) { bfs(i); } int T=read(); while(T--) { int x=read(),y=read(),k=read(); if(a[x]) { puts("no"); } else if((k%2)&&(dis[x][y+n]<=k)&&(dis[x][y+n]>=0)|| !(k%2)&&(dis[x][y]<=k)&&(dis[x][y]>=0)) { puts("yes"); } else { puts("no"); } } return 0; }