图与树

2 篇文章 0 订阅

1.邻接矩阵

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

int n,m,z[110][110];

int main()
{
	scanf("%d%d",&n,&m);
	for (int a=1;a<=m;a++)
	{
		int s,e;
		scanf("%d%d",&s,&e);
		z[s][e]=1;
		z[e][s]=1;
	}

	for (int a=1;a<=m;a++)
	{
		int s,e,d;
		scanf("%d%d%d",&s,&e,&d);
		z[s][e]=d;
	}

	return 0;
}

2.邻接表

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

const int maxn=100010;
const int maxm=200010;

int n,en,first[maxn];//first[i]代表当前第i个点的链表的第一条边的编号

struct edge
{
	int e,d;//e代表这条边的终点 d代表这条边的长度
	int next;//链表里面下一条边的编号
}ed[maxm];

void add_edge(int s,int e,int d)
{
	en++;
	ed[en].e=e;ed[en].d=d;
	ed[en].next = first[s];
	first[s] = en;
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int a=1;a<=m;a++)
	{
		int s,e,d;
		scanf("%d%d%d",&s,&e,&d);
		add_edge(s,e,d);
	}

	int now;
	for (int p=first[now];p!=0;p=ed[p].next)
		printf("%d---->%d",now,ed[p].e);

	return 0;
}

3.判断二分图

判断二分图方法-染色法:用两种颜色,对所有顶点逐个染色,且相邻顶点染不同的颜色,如果发现相邻顶点染了同一种颜色,则此图不是二分图。 当所有顶点都被染色,且没有发现同色的相邻顶点,就说明是二分图,退出。

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

const int maxn=100010;
const int maxm=200010;

int n,en,first[maxn];//first[i]代表当前第i个点的链表的第一条边的编号

int col[maxn];//col[i]=0 代表i点还没有被分到左边或者右边
//coi[i]=1 代表i分到了左边
//col[i]=2 代表i分到了右边

struct edge
{
	int e;//e代表这条边的终点
	int next;//链表里面下一条边的编号
}ed[maxm];

void add_edge(int s,int e)
{
	en++;
	ed[en].e=e;
	ed[en].next = first[s];
	first[s] = en;
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int a=1;a<=m;a++)
	{
		int s,e;
		scanf("%d%d",&s,&e);
		add_edge(s,e);
		add_edge(e,s);
	}

	col[1]=1;
	queue<int> q;//队列面存的点是那些周围点需要被标记的点
	q.push(1);
	while (q.size()!=0)
	{
		int now=q.front();
		q.pop();
		for (int p=first[now];p!=0;p=ed[p].next)
		{
			int e=ed[p].e;//now --- e
			if (col[e]==0)
			{
				col[e]=3-col[now];
				q.push(e);
			}
			else
			{
				if (col[e]==col[now])
				{
					printf("No\n");
					return 0;
				}
			}
		}
	}
	printf("Yes\n");

	return 0;
}

4.LCA 最近公共祖先

O(nm)版

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

const int maxn=100010;
const int maxm=200010;

int n,en,first[maxn];//first[i]代表当前第i个点的链表的第一条边的编号

int f[maxn],depth[maxn];//f[i]代表i号点的父亲 depth[i]代表i号点的深度

struct edge
{
	int e;//e代表这条边的终点
	int next;//链表里面下一条边的编号
}ed[maxm];

void add_edge(int s,int e)
{
	en++;
	ed[en].e=e;
	ed[en].next = first[s];
	first[s] = en;
}

void dfs(int now)//处理出now所有儿子节点的深度与父亲
{
	for (int p=first[now];p!=0;p=ed[p].next)
	{
		int e=ed[p].e;//now -- e
		if (e!=f[now])
		{
			depth[e]=depth[now]+1;
			f[e]=now;
			dfs(e);
		}
	}
}

int get_lca(int p1,int p2)//O(n)
{
	if (depth[p1]<depth[p2]) swap(p1,p2);
	while (depth[p1]>depth[p2])
		p1=f[p1];
	while (p1!=p2)
		p1=f[p1],p2=f[p2];
	return p1;
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int a=1;a<n;a++)
	{
		int s,e;
		scanf("%d%d",&s,&e);
		add_edge(s,e);
		add_edge(e,s);
	}

	depth[1]=1;
	dfs(1);

	for (int a=1;a<=m;a++)//O(nm)
	{
		int p1,p2;
		scanf("%d%d",&p1,&p2);
		printf("%d\n",get_lca(p1,p2));
	}

	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值