新牛到部队, 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\n",cnt); 61 for(i=1;i<=cnt;i++) 62 { 63 printf("%d ",ans[i]); 64 } 65 printf("\n"); 66 /*============================*///输出答案 67 return 0; 68 }