关于图论:
这篇博客主要写邻接表,今天,我们就来认识一下什么是邻接表吧,并看一看邻接表的题目怎么做吧!
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;
}