【算法笔记】图论 邻接表

关于图论:

这篇博客主要写邻接表,今天,我们就来认识一下什么是邻接表吧,并看一看邻接表的题目怎么做吧!

1.什么是邻接表

邻接表的作用大体和邻接矩阵相同,但是更加省空间。邻接矩阵使用二维数组存储的,二邻接表室友一位数组和结构体存储的,不想邻接矩阵那样定义的简单暴力,有比较特殊的读入方法。

2.邻接表的存储方式

邻接表,我们需要用一个link数组来存储所有和第i个点连通的所有点及其权值,然后通过link数组在结构体数组e上进行遍历,一直查找next知道next为0即可,y表示与第i个点所连通的店,v表示权值,next表示和i连通的下一个点。

3.邻接表的存储如何用代码实现

struct edge{
    int y,v,next;		//y表示这条边的终点编号,v是权值;
};  				//next表示同起点下条边的编号是多少
edge e[maxm+10];  //边表。
int linkk[maxn+10];  //起点表 link[i]表示由i出去的第一条边的下标是多少

void insert(int ss,int ee,int vv)//ss为起点,ee为终点,vv为权值。
{  
	e[++t].y=ee; e[t].v=vv;  	//t表示有t条边,是个全局变量。
	e[t].next=linkk[ss]; linkk[ss]=t;
}

void init(){
    scanf("%d %d %d",&n,&p,&m);
	for (int i=0;i


4.田野上的环

题目描述

FJ 让他的N (1 <= N <= 250)只编号为从1到N的奶牛在田地里玩.这些奶牛决定用M条1<=M<=N*(N+1)/2)牛绳将各自连接起来.当然,不会出现一对牛被两条及以上牛绳连接起来.输入告诉你每一条牛绳连接的两只奶牛C1和C2(1 <= c1 <= N; 1 <= c2 <= N; c1 <> c2).

FJ要求奶牛们与1号奶牛相连.现在你要帮助FJ找出所有没有与1号奶牛相连的奶牛.这里的相连既可以是直接的,也可以是间接的(特别的,1号奶牛总是与自己相连).将没有与1号奶牛相连的奶牛的编号升序输出.如果你找不到这样的一只牛,那么就输出0. 解释一下的话,看这个有6只奶牛和4个连接的例子:

此图明显有差别,请自己根据样例来画图

  1----2  4---5

   \   |

    \   |     6

     \  |

      3

很明显,4,5,6号牛没有同1号牛相连.

输入格式

第1行:两个用空格分开的整数N,M 第2..M+1行:每一行有两个整数.第i+1行描述的是绳子i连接的两只奶牛的编号,即C1和C2.

输出格式

很多行:每一行包含一个整数,意义如题目所说.升序输出.

样例数据

input

6 4
1 3
2 3
1 2
4 5

output

4
5
6
思路:

这道题就是求和1连通的个数,然后从大到小输出即可

代码:

#include
using namespace std;
struct cow
{
	int y,next;
}e[600000];
int lin[5000],t=0,n,m;
bool vis[600000];
void inse(int xxx,int yyy)
{
	e[++t].next=lin[xxx];//e数组的next节点即之前的lin[i]
	lin[xxx]=t;//更新lin
	e[t].y=yyy;//y节点为以xxx为起点的·终点
}
void dfs(int k)
{
	vis[k]=1;
	for (int i=lin[k];i;i=e[i].next)//从第i点开始遍历
	if (!vis[e[i].y]) dfs(e[i].y);
}//dfs遍历
void out(){
	bool flag=1;
	for (int i=1;i<=n;i++)
	  if (!vis[i]){
	     cout<<i<<endl;
	     flag=0;
	  }
	  if (flag) cout<<0<<endl;
}//输出
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int xx,yy;
		cin>>xx>>yy;
		inse(xx,yy);
		inse(yy,xx);
	}
	dfs(1);
	out();
}
3.犯罪团伙

题目描述

  警察抓到了n个罪犯,警察根据经验知道他们属于不同的犯罪团伙,却不能判断有多少个团伙,但通过警察的审讯,知道其中的一些罪犯之间相互认识,已知同一犯罪团伙的成员之间直接或间接认识,有可能一个犯罪团伙只有一个人。请你根据已知罪犯之间的关系,确定犯罪团伙的数量。已知罪犯的编号从1至n。

输入格式

   第一行:n(<50000,罪犯数量)。

    第二行:m(<400000,关系数量)。

   以下m行,每行两个数:i 和j,中间一个空格隔开,表示罪犯i和罪犯j相互认识。

输出格式

一个整数,犯罪团伙的数量。

样例数据

input

11
8 
1 2
4 5
3 4
1 3
5 6
7 10
5 10
8 9

output

3
思路:

求连通分量的·个数,和上述相同,即上面的题目只要dfs 1就好,这要要dfs每一个点

程序:

#include
using namespace std;
struct cow
{
	int y,next;
}e[6000000];
int lin[500000],t=0,n,m,sum=0;
bool vis[6000000]={};
void inse(int xxx,int yyy)
{
	e[++t].next=lin[xxx];
	lin[xxx]=t;
	e[t].y=yyy;
}
void dfs(int k)
{
	vis[k]=1;
	for (int i=lin[k];i;i=e[i].next)
	if (!vis[e[i].y]) dfs(e[i].y);
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int xx,yy;
		cin>>xx>>yy;
		inse(xx,yy);
		inse(yy,xx);
	}
	for (int i=1;i<=n;i++)
    	if (vis[i]==0) 
    	{
	    	dfs(i);
        	sum++;
        }
    cout<<sum;
	return 0;
}

你可能感兴趣的:(【算法笔记】图论 邻接表)