天梯赛 邻接表的使用习题+天梯赛 L2-病毒溯源另一种解法

之前用vector数组代替邻接表做了几道题  像我之前做的这个: [病毒溯源](https://blog.youkuaiyun.com/weixin_46177831/article/details/123626603?spm=1001.2014.3001.5501)
但是最近遇到一个题目,是不能用普通的vector数组来替代邻接表的,因为它加上了权重,因此 还是得学习一下邻接表的使用。用邻接表的方法再做一下这几道题。

有一棵 n (1 <= n <= 100000) 个点的树。树上的边有正边权 ( 1 <= 边权 <= 10000)。
以s (1 <= s <= n)号点为树根,求到t (1 <= t <= n)号点的边权之和。
输入格式:
第一行三个正整数n,s,t。
接下来n-1行,每行三个正整数a,b,w(表示点a和点b之间有一条边权为w的无向边)。
输出格式:
输出从点s到点t的边权和。
输入样例:
4 1 4
1 2 3
2 3 4
3 4 5
输出样例:
12

源代码:

#include <iostream>
using namespace std;
const int MAXn=100000+10;
const int MAXm=200000+10;
int n,s,t,edge,head[MAXn],vis[MAXn],len;
struct list{
	int to;
	int w;
	int nxt;
}e[MAXm];

void add_edge(int u,int v,int w){
	e[++edge].to=v;
	e[edge].nxt=head[u];
	e[edge].w=w;
	head[u]=edge;
}

void dfs(int node,int cnt){
	if(node==t){
		len=cnt;
		return;
	}
	for(int i=head[node];i;i=e[i].nxt){
		if(!vis[e[i].to]){
			vis[e[i].to]=1;
			dfs(e[i].to,cnt+e[i].w);
		}
	}
}

int main()
{
	cin>>n>>s>>t;
	int u,v,w;
	for(int i=0;i<n-1;++i){
		cin>>u>>v>>w;
		add_edge(u,v,w);
		add_edge(v,u,w);
	}
	vis[s]=true;
	dfs(s,0);
	
	cout<<len;
	return 0;
}

病毒溯源:

#include <iostream>
using namespace std;
const int MAXn=10000+10;
const int MAXm=200000+20;
int n,maxdeep;//记录最大链长 
int ans[MAXn],temp[MAXn];//记录答案序列 及辅助序列
int sou[MAXn];//寻找病毒源头 
int edge;//记录是第几条边 
int head[MAXn];//每个点的最后一条边 
struct list{//存储所有边 
	int to;
	int nxt; 
}e[MAXm];
void add_edge(int u,int v){//建边函数 
	e[++edge].to=v;
	e[edge].nxt=head[u];
	head[u]=edge;
}

bool judge(int deep){
	for(int i=1;i<=deep;++i){
		if(temp[i]>ans[i]) return false;
		else if(temp[i]<ans[i]) return true;
	}
}

void dfs(int node,int deep){
	temp[deep]=node;
	if(head[node]==0){//一条链的结尾 
		if(deep>maxdeep){
			maxdeep=deep;
			for(int j=1;j<=deep;++j)
				ans[j]=temp[j];
		}
		else if(deep==maxdeep){
			if(judge(deep)){
				for(int j=1;j<=deep;++j)
				ans[j]=temp[j];
			}
		}
		return;
	}
	for(int i=head[node];i;i=e[i].nxt){
		dfs(e[i].to,deep+1);
	}
}

int main()
{
	cin>>n;
	for(int u=0;u<n;++u){
		int k;
		cin>>k;
		for(int i=0;i<k;++i){
			int v;
			cin>>v;
			add_edge(u,v);
			sou[v]=1;
//			add_edge(v,u);
		}
	}
	int root;
	for(int i=0;i<n;++i){
		if(sou[i]==0){
			root=i;
			break;
		}
	}
	dfs(root,1);
	cout<<maxdeep<<endl;
	for(int i=1;i<maxdeep;++i)
		cout<<ans[i]<<" ";
	cout<<ans[maxdeep];
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值