2014 NOIP提高组 day2 第二题
提交次数:3
题目描述
在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。
2 .在满足条件1 的情况下使路径最短。
注意:图G 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入输出格式
输入格式:
输入文件名为road .in。
第一行有两个用一个空格隔开的整数n 和m ,表示图有n 个点和m 条边。
接下来的m 行每行2 个整数x 、y ,之间用一个空格隔开,表示有一条边从点x 指向点y 。
最后一行有两个用一个空格隔开的整数s 、t ,表示起点为s ,终点为t 。
输出格式:
输出文件名为road .out 。
输出只有一行,包含一个整数,表示满足题目᧿述的最短路径的长度。如果这样的路径不存在,输出- 1 。
代码:
1 #include<iostream> 2 #include<vector> 3 #include<queue> 4 #include<cstdio> 5 using namespace std; 6 vector<int>v[10010]; 7 vector<int>vr[10010];//反置图 8 int used[10010]; 9 int can[10010];//能通向终点的点 10 queue<int>q; 11 struct node{ 12 int num; 13 int step; 14 }; 15 queue<node>qq; 16 17 int main(){ 18 int n, m; 19 cin>>n>>m; 20 int i; 21 for(i = 1; i <= m; i++){ 22 int x, y; 23 scanf("%d%d", &x, &y); 24 v[x].push_back(y); 25 vr[y].push_back(x); 26 } 27 int s, t; 28 cin>>s>>t; 29 q.push(t); 30 can[t] = 1; 31 int k; 32 while(!q.empty()){ 33 k = q.front(); 34 q.pop(); 35 for(i = 0; i < vr[k].size(); i++){ 36 if(!can[vr[k][i]]){ 37 q.push(vr[k][i]); 38 can[vr[k][i]] = 1; 39 } 40 } 41 } 42 for(i = 1; i <= n; i++){ 43 if(!can[i]){ 44 for(int j = 0; j < vr[i].size(); j++) 45 if(can[vr[i][j]]==1) can[vr[i][j]] = -1; 46 } 47 } 48 if(can[s]==0||can[s]==-1){ 49 cout<<"-1"; 50 return 0; 51 } 52 node p; 53 p.num = s; p.step = 0; 54 qq.push(p); 55 used[s] = true; 56 // for(i = 1; i <= n; i++){ 57 // if(can[i]) cout<<i<<" "; 58 // } 59 // cout<<endl; 60 61 while(!qq.empty()){ 62 node k = qq.front(); 63 if(k.num==t){ 64 cout<<k.step; 65 break; 66 } 67 qq.pop(); 68 for(i = 0; i < v[k.num].size(); i++){ 69 if(!used[v[k.num][i]]&&can[v[k.num][i]]!=0&&can[v[k.num][i]]!=-1){ 70 p.num = v[k.num][i]; 71 p.step = k.step+1; 72 qq.push(p); 73 used[p.num] = true; 74 } 75 } 76 } 77 return 0; 78 }
备注:
两遍BFS。注意题目含义是,路径上所有点的所有出度都是可以到达终点的。因此不符合要求的点有两类,第一类是不能到达终点的点(用can[i]=0表示),第二类是直接指向不能到达终点的点(用can[i]=-1表示)。所以存一个反置图,首先从终点往回BFS,标记下能到达的点,再把不能到达的点所直接连接的点标记为-1。
犯了两个错误,第一是,这两类点必须分开表示,如果在排查第二类点的时候也赋值为0,那么在往后接着找时,这个点会被视作第一类点,所以会删掉不应该删的点。第二,忘了写used[p.num]=true,即标黄那行,因为图中可能存在环,如果不进行判重就会超时。