NOIP2014 寻找道路

陈子骏

2018-10-16 16:28:38

Personal

题目大意: 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。 2 .在满足条件1 的情况下使路径最短。 Solution 首先,预处理,把每条边反向。 从终点开始bfs,标记从终点开始可以走到的点。 第二步,枚举每一个点,如果这个点没有被标记,则枚举它的每一条出边(反向后的),如果它指向的点被标记,则说明这个被标记的点不合法,删除。 第三步,在合法点上bfs,单源最短路。找到答案 ``` #include<bits/stdc++.h> using namespace std; int n,m; struct edg{ int next,to; }edge[200001]; edg hhhh[200001]; int head[200001],hed[200001]; int cnt,qwq; int sec_ve[200001]; int ve[20001]; int vis[20001],dis[20001]; void add(int a,int b) { edge[++cnt].to=b; edge[cnt].next=head[a]; head[a]=cnt; hhhh[cnt].to=a; hhhh[cnt].next=hed[b]; hed[b]=cnt; } int s,t; int x,y; queue<int>q; queue<int>k; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)dis[i]=9999; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(x!=y)add(x,y); } scanf("%d%d",&s,&t); k.push(t); ve[t]=1; while(!k.empty()) { int u=k.front(); k.pop(); for(int i=hed[u];i;i=hhhh[i].next) { int v=hhhh[i].to; if(!ve[v]){ ve[v]=1; k.push(v); } } } for(int i=1;i<=n;i++)if(!ve[i]) for(int e=hed[i];e;e=hhhh[e].next) sec_ve[hhhh[e].to]=true; for(int i=1;i<=n;i++)vis[i]=0; dis[s]=0; q.push(s); vis[s]=1; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; if(!ve[u]||sec_ve[u])continue; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(dis[v]>dis[u]+1){ dis[v]=1+dis[u]; if(!vis[v]) { vis[v]=1; q.push(v); } } } } if(dis[t]<9999)printf("%d",dis[t]); else printf("-1"); } ```