• 洛谷-跑步-NOI导刊2010提高


    新牛到部队, CG 要求它们每天早上搞晨跑,从A农场跑到B农场。从A农场到B农场中有n-2个路口,分别标上号,A农场为1号, B农场为n号,路口分别为 2 ..n -1 号,从A农场到B农场有很多条路径可以到达,而CG发现有的路口是必须经过的,即每条路径都经过的路口,CG要把它们记录下来,这样CG就可以先到那个路口,观察新牛们有没有偷懒,而你的任务就是找出所有必经路口。

    输入输出格式

    输入格式:

    第一行两个用空格隔开的整数 n ( 3<=n<=2000 )和e ( 1<=e<= 8000 )。

    接下来从第2到第e + 1行,每行两个用空格隔开的整数p和q,表示路口p和q之间有路径直达。

    输入数据保证必经路口一定存在,并且每个路口都和A农场、B农场相连通。

    输出格式:

    第一行一个整数m,表示必经路口的数目。

    第二行按从小到大的顺序依次输出每个必经路口的编号,每两个数之间用一个空格隔开。

    输入输出样例

    输入样例#1: 
    6 6
    1 2
    2 4
    2 3
    3 5
    4 5
    5 6
    
    输出样例#1: 
    2
    2 5


    思路:就按照题目中的样子来模拟就好。
    把除了起点和终点以外的所有点都试着删除一下,看看能否走到终点,如果能走到,则这个点一定不是必经点,反之则是必经点。

    代码如下:
     1 #include <stdio.h>
     2 int cnt=0;
     3 int head[20000]={0};//表头数组 
     4 int flag=0;//1表示能走到终点,0表示不能
     5 int ans[20002]={0};//记录答案数组 
     6 int n,e;//点、边 
     7 int temp[20002]={0};//离线记录需要删除的点 
     8 struct Edge//领接表存储类型 
     9 {
    10     int next,to;
    11 }edge[16002];//一定要大点!!应该是边数的两倍多一点!!
    12 
    13 void add(int x,int y)//添加边
    14 {
    15     cnt++;
    16     edge[cnt].next=head[x];
    17     edge[cnt].to=y;
    18     head[x]=cnt;
    19 }
    20 
    21 void dfs(int start,int del)
    22 {
    23     if(start==n)//搜到了终点,不是必经点 
    24     {
    25         flag=1;
    26         return ;
    27     }
    28     temp[start]=del;//离线记录需要删除的点 
    29     for(int i=head[start];i!=0;i=edge[i].next)//从start开始,每次搜索start所连接的点 
    30     {
    31         int y=edge[i].to;//start所连接的点
    32         if(temp[y]!=del&&y!=del) dfs(y,del);//如果走到的店点不是暂时删除的点,往下搜索,更新start为y 
    33     }
    34 }
    35 
    36 int main()
    37 {
    38     int p,q;
    39     int i;
    40     int ans[20002]={0};//记录答案
    41     scanf("%d%d",&n,&e);
    42     for(i=1;i<=e;i++)//添加无向图 
    43     {
    44         scanf("%d%d",&p,&q);
    45         add(p,q);
    46         add(q,p);
    47     }
    48     cnt=0;//记录答案数目
    49     for(i=2;i<n;i++)
    50     {
    51         flag=0;
    52         dfs(1,i);//从1号节点开始跑,依次删除编号为i的节点 
    53         if(flag==0)//如果i是必经点 
    54         {
    55             cnt++;
    56             ans[cnt]=i;
    57         } 
    58     }
    59     /*============================*///输出答案 
    60     printf("%d
    ",cnt);
    61     for(i=1;i<=cnt;i++)
    62     {
    63         printf("%d ",ans[i]);
    64     }
    65     printf("
    ");
    66     /*============================*///输出答案 
    67     return 0;
    68 }
     
  • 相关阅读:
    UITextField的简单操作和实际应用
    iOS
    单例传值
    改良UIScrollView滚动视图
    省市便利 UIPicherView
    滚动视图UIScrollView
    label自适应
    将图像设置成圆形
    笔记
    笔记
  • 原文地址:https://www.cnblogs.com/geek-007/p/9929433.html
Copyright © 2020-2023  润新知