题意:

         给定一个由箭头组成的赛道,箭头起始点有标号,运动员从0点出发,只能沿箭头方向跑,到下一点后,可选择任意箭头继续跑。

路线有以下特点:

        1,每一点都能从出发点到达

        2,每一点都可到达终点

        3,终点无向外的箭头

运动员要到达终点,不要求经过路线上所有点。但路线上有些点为必经点。若比赛分两天进行,要把赛道分成完全分离的两部分,这两部分只有一个分裂点有重合。

       一.  找到所有必经点

       二.  找到所有分裂点

 

输入:

        前n行,每行输入的数字为i点出发的箭头可到达的点,以-2结束

        最后一行为-1,表示输入结束

输出:

        第一行输出必经点个数和所有的必经点

        第二行输出分裂点个数和所有的分裂点

 

        先从路线中删除i点,用dfs搜索出发点可达位置,若不能到达终点,则i为必经点。若i为分裂点,则i必定为必经点。在找到一个必经点后,枚举所有起始点能到达的点和不能到达的点,判断这两类点间是否有边相连,若有边相连,则i不为分裂点。

 

 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std ;
 4 int data[1000][1000], visited[1000], n ;
 5 void bfs(int s){                //宽度优先搜索
 6     int i, open, closed, queue[1000] ;
 7     visited[s] = 0 ;
 8     queue[1= s ;
 9     open = 1 ;
10     closed = 1 ;
11     while(open<=closed){
12         for(i=0; i<n; i++)
13             if(visited[i]==-1&&data[queue[open]][i]!=0){
14                 visited[i] = visited[queue[open]] + 1 ;
15                 closed ++ ;
16                 queue[closed] = i ;
17             }
18         open ++ ;
19     }
20 }
21 int main(){
22     int data1[1000][1000], i, j, a[1000], b[1000], a1=0, b1=0 ;
23     cin >> n ;
24     for(i=1;; i++){         //读取完整路线
25         while(true){
26             cin >> j ;
27             if(j==-2)   break ;
28             data1[i][j] = 1 ;
29         }
30         cin >> j ;
31         if(j==-1)   break ;
32         data1[i+1][j] = 1 ;
33     }
34     memset(visited, -1sizeof(visited)) ;
35     for(i=1; i<n; i++){
36         data = data1 ;              //数组复制,直接简化了
37         for(j=1; j<=n; j++){
38             data[i][j] = 0 ;
39             data[j][i] = 0 ;
40         }
41         bfs(0) ;    //搜索删除i点后顶点所能到达的位置
42         if(visited[n]==-1){ //若不能到达终点,则i为必经点
43             a[a1] = i ;
44             a1 ++ ;
45             bool fund = true ;
46             for(int k=0; k<n; k++)
47                 for(int p=0; p<=n; p++){//若删除i后0可达的点和不可达的点间有交集,则i不为分裂点
48                     if(visited[k]!=-1&&visited[p]==-1&&(data[k][p]!=0||data[p][k]!=0)){
49                         fund = false ;
50                         break ;
51                     }
52                 }
53             if(fund){
54                 b[b1] = i ;
55                 b1 ++ ;
56             }
57         }
58     }
59     cout << "必经点个数为: " << a1 << "  分别为:" ;
60     for(i=0; i<a1; i++)
61         cout << a[i] << " " ;
62     cout << endl ;
63     cout << "分裂点个数为:" << b1 << "  分别为:" ;
64     for(i=0; i<b1; i++)
65         cout << b[i] << " " ;
66     return 0 ;
67 }

 

 

posted on 2011-08-20 15:59  追逐.  阅读(276)  评论(0编辑  收藏  举报