建图遍历。(2018-1-29)

可以用下面两个代码

来加速cin 与cout ,这样cin的速度就和sanf差不多了,

注意,这两个代码的头文件是 iostream

并且如果用了这两个,就不要用scanf ,getchar,gets,fgets,fscanf了,

他的作用是关于 iostream和stdio的同步,让c++和c的输入出不在挂钩了(具体原理我也不清楚哈)

还有就是,用“\n”而不是 endl,也可以提高速度。


std::ios::sync_with_stdio(false);
    cin.tie(0);

第二个是取消cin与cout的绑定,去掉了也没用。

但是数据量大还是推荐用scanf,

开加速也可能会卡。


邻接矩阵:矩阵的大小由点的平方来决定。权值只有0 ,1 。0代表不连通1代表联通,有向图是单向链接

#include <bits/stdc++.h>

using namespace std;

struct Edge
{
	int to, next;
}data[10010];

int head[1010], cnt;

void addEdge(int from, int to)
{
	data[cnt].to = to;
	data[cnt].next = head[from];
	head[from] = cnt++;
}

int main(int argc, char **argv)
{
	memset(head, -1, sizeof(head));
	int from, to;
	int vertex, edge;
	scanf("%d %d", &vertex, &edge);
	for (int i = 0; i < edge; i++)
	{
		scanf("%d %d", &from, &to);
		addEdge(from, to);
	}
	return 0;
}
邻接表的代码实现。
   
   
01 #include <bits/stdc++.h>
02  
03  
04 //牛洪凯版。。。。。静态结构体数组,
05 //head不存值通过在数组上往外链接指针链表。
06 //把每个点能够指向的点依次插入。
07 //错误::忘记遍历时忘记了p=p->next
08  
09  
10 using namespace std;
11 struct code
12 {
13     int e;
14     code *next;
15 } head[5005],*p,*r;
16 int main()
17 {
18     int q,n,i,j,x,y,s;
19     while(~scanf("%d",&n))
20     {
21         for(i=0; i<n; i++)
22             head[i].next=NULL;
23         for(i=0; i<n; i++)
24         {
25             for(j=0; j<n; j++)
26             {
27                 scanf("%d",&x);
28                 if(x==1)
29                 {
30                     p=new code;
31                     p->e=j;
32                     p->next=head[i].next;
33                     head[i].next=p;
34                 }
35             }
36         }
37         scanf("%d",&q);
38         while(q--)
39         {
40             scanf("%d%d",&x,&y);
41             p=head[x].next;
42             s=1;
43             while(p!=NULL)
44             {
45                 if(p->e==y)
46                 {
47                     printf("Yes\n");
48                     s=0;
49                     break;
50                 }
51                 p=p->next;
52             }
53             if(s==1)printf("No\n");
54         }
55     }
56     return 0;
57 }
58  


数据结构实验之图论四:迷宫探索

Time Limit: 1000MS  Memory Limit: 65536KB

Problem Description

有一个地下迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关;请问如何从某个起点开始在迷宫中点亮所有的灯并回到起点?

Input

连续T组数据输入,每组数据第一行给出三个正整数,分别表示地下迷宫的结点数N(1 < N <= 1000)、边数M(M <= 3000)和起始结点编号S,随后M行对应M条边,每行给出一对正整数,表示一条边相关联的两个顶点的编号。

 

Output

若可以点亮所有结点的灯,则输出从S开始并以S结束的序列,序列中相邻的顶点一定有边,否则只输出部分点亮的灯的结点序列,最后输出0,表示此迷宫不是连通图。
访问顶点时约定以编号小的结点优先的次序访问,点亮所有可以点亮的灯后,以原路返回的方式回到起点。

Example Input

1
6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5

Example Output

1 2 3 4 5 6 5 4 3 2 1
   
   
01 #include <bits/stdc++.h>
02  
03 using namespace std;
04  
05 int vis[3105],ma[3105][3105],a[3100];
06 //vis储存点访问状态。。。a[][]点与点之间是否联通。
07 int num,k,m;
08 //表示点数和边数
09 /*深度优先遍历相当于二叉树中的前序遍历,
10 而且深度优先遍历中运用了递归,从进入迷宫到出迷宫,
11 从起点进入最后又从起点出来。递归的先递归到最后最低端,
12 然后再由最低端递归到最开始的地方,
13 二者类似。所以如果是连通图每个点都被来回两次访问,
14 如果不是连通图那么访问次数就小于2*n-1;
15 (最后一个点访问了一次); 如果是连通图的话,
16 DFS深度优先遍历遍历了每个点两次。
17 迷宫图如果是连通图的话,那么每个灯就路过了两次。*/
18 void dfs(int i)//深度搜索,从某个点开始 。
19 {
20     int j;
21     vis[i]=1;
22     a[num++]=i;
23     for(j=1; j<=k; j++)//点数从0到存在的点
24     {
25         if(ma[i][j]==1&&vis[j]==0)//两个点之间有无向线段。
26         {
27             vis[j]=1;//标记已经走过。
28             dfs(j);//深度搜索从j开始。
29             a[num++]=i;
30         }
31     }
32 }
33 int main()
34 {
35     int n,i,u,x,y;
36     cin>>n;
37     while(n--)
38     {
39         cin>>k>>m>>u;
40         memset(vis,0,sizeof(vis));
41         memset(ma,0,sizeof(ma));
42         for(i=0; i<m; i++)
43         {
44             cin>>x>>y;
45             ma[x][y]=ma[y][x]=1;
46         }
47         num=0;
48         dfs(u);
49         for(i=0;i<num;i++)
50         {
51         if(i==0)
52         cout<<a[i];
53         else
54         cout<<" "<<a[i];
55         }
56         if(num!=2*k-1)
57         cout<<" 0";
58         cout<<endl;
59     }
60     return 0;
61 }

数据结构实验之图论四:迷宫探索

Time Limit: 1000MS  Memory Limit: 65536KB

Problem Description

有一个地下迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关;请问如何从某个起点开始在迷宫中点亮所有的灯并回到起点?

Input

连续T组数据输入,每组数据第一行给出三个正整数,分别表示地下迷宫的结点数N(1 < N <= 1000)、边数M(M <= 3000)和起始结点编号S,随后M行对应M条边,每行给出一对正整数,表示一条边相关联的两个顶点的编号。

 

Output

若可以点亮所有结点的灯,则输出从S开始并以S结束的序列,序列中相邻的顶点一定有边,否则只输出部分点亮的灯的结点序列,最后输出0,表示此迷宫不是连通图。 访问顶点时约定以编号小的结点优先的次序访问,点亮所有可以点亮的灯后,以原路返回的方式回到起点。

Example Input

1
6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5

Example Output

1 2 3 4 5 6 5 4 3 2 1

    
    
01 #include <bits/stdc++.h>
02  
03 using namespace std;
04  
05 int vis[3105],ma[3105][3105],a[3100];
06 //vis储存点访问状态。。。a[][]点与点之间是否联通。
07 int num,k,m;
08 //表示点数和边数
09 /*深度优先遍历相当于二叉树中的前序遍历,
10 而且深度优先遍历中运用了递归,从进入迷宫到出迷宫,
11 从起点进入最后又从起点出来。递归的先递归到最后最低端,
12 然后再由最低端递归到最开始的地方,
13 二者类似。所以如果是连通图每个点都被来回两次访问,
14 如果不是连通图那么访问次数就小于2*n-1;
15 (最后一个点访问了一次); 如果是连通图的话,
16 DFS深度优先遍历遍历了每个点两次。
17 迷宫图如果是连通图的话,那么每个灯就路过了两次。*/
18 void dfs(int i)//深度搜索,从某个点开始 。
19 {
20     int j;
21     vis[i]=1;
22     a[num++]=i;
23     for(j=1; j<=k; j++)//点数从0到存在的点
24     {
25         if(ma[i][j]==1&&vis[j]==0)//两个点之间有无向线段。
26         {
27             vis[j]=1;//标记已经走过。
28             dfs(j);//深度搜索从j开始。
29             a[num++]=i;//不同于深度遍历之处在于这里,在递归结束后一层一层的往回返回并且进入数组中。
30         }
31     }
32 }
33 int main()
34 {
35     int n,i,u,x,y;
36     cin>>n;
37     while(n--)
38     {
39         cin>>k>>m>>u;
40         memset(vis,0,sizeof(vis));
41         memset(ma,0,sizeof(ma));
42         for(i=0; i<m; i++)
43         {
44             cin>>x>>y;
45             ma[x][y]=ma[y][x]=1;
46         }
47         num=0;
48         dfs(u);
49         for(i=0;i<num;i++)
50         {
51         if(i==0)
52         cout<<a[i];
53         else
54         cout<<" "<<a[i];
55         }
56         if(num!=2*k-1)
57         cout<<" 0";
58         cout<<endl;
59     }
60     return 0;
61 }

数据结构实验之图论二:基于邻接表的广度优先搜索遍历

Time Limit: 1000MS  Memory Limit: 65536KB

Problem Description

给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列。(同一个结点的同层邻接点,节点编号小的优先遍历)

Input

输入第一行为整数n(0< n <100),表示数据的组数。 对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,0< t<k),表示有m条边,k个顶点,t为遍历的起始顶点。  下面的m行,每行是空格隔开的两个整数u,v,表示一条连接u,v顶点的无向边。

Output

输出有n行,对应n组输出,每行为用空格隔开的k个整数,对应一组数据,表示BFS的遍历结果。

Example Input

1
6 7 0
0 3
0 4
1 4
1 5
2 3
2 4
3 5

Example Output

0 3 4 2 5 1

   
   
01 #include <bits/stdc++.h>
02 #include<stdio.h>
03 using namespace std;
04 int b[11],que[11],a[10][10];
05 //队列先进先出。
06  
07 void bfs(int r,int len )
08 {
09 int i=0,vis[11];//标记是否走过。
10 memset(vis,0,sizeof(vis));//初始化假设所有的点都未走过。
11 int s=0,e=0;
12 vis[r]=1;
13 //e入队s出对。并且标记起始顶点已走过。
14 que[e++]=r;
15 b[i++]=r;
16 //b为输出数组。
17 while(s<e)
18 {
19 for(int j=0;j<len;j++)
20 {
21 if(a[que[s]][j]==1&&!vis[j])
22 {
23 que[e++]=j;
24 vis[j]=1;
25 b[i++]=j;
26 }
27 }
28 s++;
29 }
30 }
31 int main()
32 {
33 int n,m,t,k,i,j;
34 scanf("%d",&n);
35 while(n--)
36 {
37 scanf("%d%d%d",&k,&m,&t);
38 memset(a,0,sizeof(a));
39 while(m--)
40 {
41 scanf("%d%d",&i,&j);
42 a[i][j]=a[j][i]=1;
43 }
44 bfs(t,k);
45 for(i=0;i<k;i++)
46 {
47 cout<<b[i];
48 (i==k-1?cout<<endl:cout<<" ");
49 }
50 }
51     return 0;
52 }

Catch That Cow

Time Limit: 2000MS  Memory Limit: 65536KB

Problem Description

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting. * Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute * Teleporting: FJ can move from any point X to the point 2 × X in a single minute. If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

Input

Line 1: Two space-separated integers: N and K

Output

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

Example Input

5 17

Example Output

4

题意:

          FJ要抓奶牛。

         开始输入N(FJ的位置)K(奶牛的位置)。

         FJ有三种移动方法:1、向前走一步,耗时一分钟。

                                              2、向后走一步,耗时一分钟。

                                             3、向前移动到当前位置的两倍N*2,耗时一分钟。

       问FJ抓到奶牛的最少时间。PS:奶牛是不会动的。

 

思路:1、如果FJ不在奶牛后面,那么他只有一步步往后移动到奶牛位置了,即N>=K时,输出N-K即可。

          2、否则bfs+队列查找(具体见下面的分析&&代码区)

相关算法:

            1、STL中的队列。(PS:周四才在数据结构上了解bfs的真正思想,惭愧啊!)

                需要的头文件:STL是C++中的 #include<iostream>

                                                                 using namespace std;

                                         queue队列容器的头文件 #include<queue>

               queue队列的相关用法:先进先出(FIFO)

                                                     入队push()   //即插入元素

                                                     出队pop()    //即删除元素

                                                     front()        //读取队首元素

                                                     back()       //读取队尾元素

                                                     empty()     //判断队列是否为空

                                                     size()        //读取队列当前元素的个数         

              2、bfs思想:节点进行广度优先搜索的顺序。

                                                                         

                               搜索实现方法(非递归):

                               算法思想:1.设置一个队列Q,从顶点出发,遍历该顶点后让其进队;

                                                 2.出队一个顶点元素,求该顶点的所有邻接点(对应于此题即FJ的三种走法),

                                                    对于没有遍历过的邻接点遍历之,并 让其进队;

                                                 3.若队空停止,队不空时继续第2步。

深度优先搜索练习之神奇的矩环

Time Limit: 1000MS  Memory Limit: 65536KB

Problem Description

小鑫的女朋友被魔王抢走了! 魔王留给小鑫一张n*m大的表,上面有各种各样的颜色,用A-Z这26个字母来表示。魔王留给他一个任务,如果小鑫可以在这张表中找出任意一个长度大于1的环,并且这个环的颜色是相同的,魔王就把小鑫的女朋友还给他。为了从魔王手中夺回他的女朋友,小鑫请你帮忙,你能帮帮他吗?

Input

多组输入。 每组的第一行有两个整数n,m。代表表的大小。 接下来是由A-Z的一些字母所构成的n行m列的表。 1<=n,m<=200

Output

如果可以救回他的女朋友,输出Yes,否则输出No

Example Input

4 7
ABCBBAA
BCBCBCB
AABBCCA
ACCCBBB
10 3
AAC
ABB
BBA
AAC
CBC
CCA
CBB
CCA
CCB
BAA

Example Output

No
Yes

   
   
#include <bits/stdc++.h>
02 using namespace std;
03 char dap[205][205];
04 int vis[201][201];
05 int n,m,flag;
06 int go[4][2]= {{1,0},{0,1},{0,-1},{-1,0}};
07 void dfs(int x,int y,int x1,int y1)
08 {
09     vis[x][y]=1;//每次进来DFS都会标记。//
10     for(int t=0; t<4; t++)
11     {
12         int i=x+go[t][0];
13         int j=y+go[t][1];
14         if(i>=0&&i<n&&j>=0&&j<m&&dap[i][j]==dap[x][y])
15         {
16             if(!vis[i][j])//没被标记就继续走直到走不动或者发现环。
17                 dfs(i,j,x,y);//递归调用。
18                 else if(i!=x1&&j!=y1)//当前节点的上一节点不是父亲节点并已经被访问过那么就构成了环,
19                 {
20                     flag=1;
21                     return ;
22                 }
23         }
24     }
25 }
26 int main()
27 {
28     std::ios::sync_with_stdio(false);
29     while(cin>>n>>m)
30     {
31         flag=0;
32         memset(vis,0,sizeof(vis));
33         for(int i=0;i<n;i++)
34         cin>>dap[i];
35         for(int i=0;i<n;i++)
36         {
37         for(int j=0;j<m;j++)
38             {
39                 if(!vis[i][j])
40                 {
41                 dfs(i,j,i,j);//只要没被标记过就可以从这里开始去寻找环,
42                 if(flag)
43                 break;
44                 }
45             }
46  
47         if(flag)
48         break;
49         }
50         if(flag)
51         cout<<"Yes"<<endl;
52         else
53             cout<<"No"<<endl;
54     }
55     return 0;
56 }

猜你喜欢

转载自blog.csdn.net/beposit/article/details/79191314