链式前向星

一、定义

链式前向星本质上是用链表实现邻接表来存图。

二、创建

1 数组

使用数组时,需要4个变量:head,ver,Next,tot。其中,tot在初始化时要赋值为-1.

int head[100005],ver[100005],Next[100005],tot=-1;

1.1 add建图

void add(int x,int y){
	ver[++tot]=y;
	Next[tot]=head[x];
	head[x]=tot;
}

若有权值,则增加edge数组。

void add(int x,int y,int z){
    ver[++tot]=y;
    edge[tot]=z;
    Next[tot]=head[x];
    head[x]=tot;
}

1.2 遍历

若遍历节点i,循环从 h e a d [ i ] head[i] head[i]开始,每次取Next。

for(int j=head[i];j!=-1;j=Next[j])

2 结构体

将变量用结构体封装起来即可。

3 vector(最简洁)

优点:空间可控,代码简短

3.1 建图

不带权:

vector<vector<int> >e(100);//定义
e[x].push_back(y);//加边

带权:

vector<vector<pair<int,int> > >e(100);//定义
e[x].push_back(make_pair(y,z));//加边

对,你没看错,结束了。

3.2 遍历(对于带权)

遍历节点i:

for(int j=e[i].size()-1;j>=0;j--){
	cout<<i<<" "<<e[i][j].first<<" "<<e[i][j].second<<endl;
}

三、实践

1 模板链式前向星

题目描述

读入 n n n个点, m m m条边,以及 f l a g flag flag,若 f l a g = = 1 flag==1 flag==1,则图有向,否则无向。对每个点输出它的每一条边。

AC代码

#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
vector<vector<pair<int,int> > >e(100);//定义
vector<vector<int> >e(100);
ll n,m,flag;
ll x,y,z;
int main(){
	cin>>n>>m>>flag;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>z;
		e[x].push_back(make_pair(y,z));//加边 
		if(flag==0){
			e[y].push_back(make_pair(x,z));//加边 
		}
	}
	for(int i=1;i<=m;i++){
		for(int j=e[i].size()-1;j>=0;j--){
			cout<<i<<" "<<e[i][j].first<<" "<<e[i][j].second;pr;
		}
		if(e[i].size()==0){
			pr;
		}
	}
	return 0;
}

2 树

题目描述

在这个问题中,给定一个值 S S S和一棵树。在树的每个节点有一个正整数,问有多少条路径的节点总和达到 S S S。路径中节点的深度必须是升序的。假设节点 1 1 1是根节点,根的深度是 0 0 0,它的儿子节点的深度为 1 1 1。路径不必一定从根节点开始。

AC代码

#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const ll N=1e6+5;
ll n,s;
ll h[N],e[N],ne[N],idx=0;
ll a[N],sum[N],st[N];
void add(ll x,ll y){
	e[idx]=y;ne[idx]=h[x];h[x]=idx++;
}
ll ans=0;
void dfs(ll u,ll fa){
	sum[u]=sum[fa]+a[u];
	st[sum[u]]++;
	ans+=st[sum[u]-s];
	for(int i=h[u];~i;i=ne[i]){
		dfs(e[i],u);
	}
	st[sum[u]]--;
}
int main(){
	memset(h,-1,sizeof h);
	scanf("%d%lld",&n,&s);
	for (ll i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	for (ll i=1;i<n;i++){
		ll x,y;
		scanf("%lld%lld",&x,&y);
		add(x,y);
	}
	st[0]=1;
	dfs(1,0);
    printf("%lld",ans);
    return 0;
}  

3 Tree Cutting

题目描述

Farmer John的网络是树形的,连接着 N N N个牛棚。Bessie打算切断某一个牛棚的电源,使和这个牛棚相连的所有电缆全部中断。之后,就会存在若干子网络。为保证破坏够大,每一个子网的牛棚数不得超过总牛棚数的一半。

AC代码

/*
not only
树的重心
but also
DFS找儿子+枚举牛棚
*/
#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
using namespace std;
ll n,size[10005];
vector<ll>e[10005],s[10005];
void dfs(ll u,ll fa){
	size[u]=1;
	for(int i=0;i<e[u].size();i++){
		ll v=e[u][i];
		if(v==fa){
			continue;
		}
		dfs(v,u);
		s[u].push_back(v);
		size[u]+=size[v];
	}
}
int main(){
	cin>>n;
	for(int i=1;i<n;i++){
		ll x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	dfs(1,-1);
	ll flag1=1;
	for(ll i=1;i<=n;i++){
		bool flag2=1;
		for(ll j=0;j<s[i].size();j++){
			ll u=s[i][j];
			if(size[u]>n/2){
				flag2=0;
				break;
			}
		}
		if(flag2&&size[i]>=n/2){
			printf("%lld",i);pr;
			flag1=0;
		}
	}
	if(flag1){
		printf("NONE");
	}
	return 0;
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值