链接:Miku
--------------------------------------------
一道很好的bfs,dfs混合练手题
--------------------------------------------
这一道题看第一眼:愚蠢的bfs求最短路,有什么难的!
然后看见了一堆附加条件:
1 路径上的所有点的出边所指向的点都直接或间接与终点连通。 2 在满足条件11的情况下使路径最短
等等,与终点联通?难道我们要把每一个点dfs能不能行吗?
然而你想一想,如果你能从这个点走到终点,那么倒着走不久走回来了?
(然而这是有向图额)
那么就建反图,dfs所有的能到终点的点
void dfs(int now){ if(vis[now]) return ; vis[now]=1; for(int i=h2[now];i;i=e2[i].ne){ dfs(e2[i].to); } }
-------------------------------------------
预处理结束,重新看一下条件1,好吧,还有一步
预处理
for(int i=1;i<=n;++i){ int f=1; for(int j=h1[i];j;j=e1[j].ne){ if(!vis[e1[j].to]){ f=0; break; } } if(!f){ vis2[i]=1; } }
---------------------------------------------
处理完这些后,就是个简单的bfs了
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 using namespace std; 5 int vis[10001]; 6 int p; 7 int p2; 8 struct b{ 9 int to; 10 int ne; 11 }e1[200001],e2[200001]; 12 struct bb{ 13 int p; 14 int t; 15 } ; 16 queue <bb> q; 17 int vis2[10001]; 18 int n,m; 19 int x,y; 20 int dis[10001]; 21 int h1[10001],h2[10001]; 22 int s,t; 23 void add(int f,int t){ 24 p++; 25 e1[p].to=t; 26 e1[p].ne=h1[f]; 27 h1[f]=p; 28 } 29 void add2(int f,int t){ 30 p2++; 31 e2[p2].to=t; 32 e2[p2].ne=h2[f]; 33 h2[f]=p2; 34 } 35 void dfs(int now){ 36 if(vis[now]) 37 return ; 38 vis[now]=1; 39 for(int i=h2[now];i;i=e2[i].ne){ 40 dfs(e2[i].to); 41 } 42 } 43 void bfs(int st){ 44 bb now; 45 now.p=st; 46 now.t=0; 47 q.push(now); 48 while(!q.empty()){ 49 now=q.front(); 50 q.pop(); 51 vis2[now.p]=1; 52 if(now.p==t){ 53 cout<<now.t; 54 return ; 55 } 56 for(int i=h1[now.p];i;i=e1[i].ne){ 57 int v=e1[i].to; 58 if(vis[v]&&!vis2[v]){ 59 bb nn; 60 nn.p=v; 61 nn.t=now.t+1; 62 q.push(nn); 63 } 64 } 65 } 66 cout<<-1; 67 } 68 int main(){ 69 scanf("%d%d",&n,&m); 70 for(int i=1;i<=m;++i){ 71 scanf("%d%d",&x,&y); 72 add(x,y); 73 add2(y,x); 74 } 75 scanf("%d%d",&s,&t); 76 dfs(t); 77 for(int i=1;i<=n;++i){ 78 int f=1; 79 for(int j=h1[i];j;j=e1[j].ne){ 80 if(!vis[e1[j].to]){ 81 f=0; 82 break; 83 } 84 } 85 if(!f){ 86 vis2[i]=1; 87 } 88 } 89 bfs(s); 90 return 0; 91 }