首页 > 其他分享 >基环树

基环树

时间:2023-05-12 13:36:15浏览次数:33  
标签:rt head int LL 基环树 maxn include

 

1584:骑士

每个骑士都有讨厌的对象,构成一个环,求最大值(能取的最大战斗力)

#include<queue>
#include<iostream>
#include<algorithm> 
typedef long long LL;
#define INF 1e9
using namespace std;
const int maxn=1e6+10;
int n,head[maxn],w[maxn],idx;
LL f[maxn][2],sum;
int r1,r2,vis[maxn];
struct node{
	int to,nex;
}e[maxn];
void adde(int x,int y){  //单向边 
	e[++idx]={y,head[x]}; 
	head[x]=idx;
}
void findd(int x,int rt){  //找出两个根 
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nex){
		int v=e[i].to;
		if(v==rt) {
			r1=x;r2=v;
			return;
		}
		if(vis[v]) continue;
		findd(v,rt);
	}
}

LL dfs(int u,int rt){
	f[u][0]=0;f[u][1]=w[u];
	for(int i=head[u];i;i=e[i].nex){
		int v=e[i].to;
		if(v==rt) continue;
		dfs(v,rt);
		f[u][0]+=max(f[v][0],f[v][1]);
		f[u][1]+=f[v][0];
	}
	return f[u][0];
}
int main(){
	scanf("%d",&n);
	for(int v=1,u;v<=n;v++){
		scanf("%d %d",&w[v],&u);
		adde(u,v);
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			r1=r2=0;
			findd(i,i);
			if(r1){
				LL res1=dfs(r1,r1);
				LL res2=dfs(r2,r2);
				sum+=max(res1,res2);
			}
			
		}
	}
	printf("%lld\n",sum);
	return 0;
}

另一种写法:双向边

#include<queue>
#include<iostream>
#include<algorithm> 
typedef long long LL;
#define INF 1e9
using namespace std;
const int maxn=1e6+10;
int n,head[maxn],w[maxn],idx=1;
LL f[maxn][2],sum;
int r1,r2,vis[maxn];
struct node{
	int to,nex;
}e[maxn<<1];  //双向边 
int be[maxn<<1];//双向边 
void adde(int x,int y){  //单向边 
	e[++idx]={y,head[x]}; 
	head[x]=idx;
}
bool findd(int x,int inv){  //找出两个根 
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nex){
		if(i==(inv^1)) continue; //是反向边 
		int v=e[i].to;
		if(!vis[v]){
			if(findd(v,i)) return 1;
		} else{
			r1=x;r2=v;be[i]=1;be[i^1]=1; //标记正反向都不能走
			return 1; 
		}
	}
	return 0;
}

LL dfs(int u,int inv){ //树上dp 
	vis[u]=1;
	f[u][0]=0;f[u][1]=w[u];
	for(int i=head[u];i;i=e[i].nex){
		int v=e[i].to;
		if(be[i]||i==(inv^1)) continue;
		dfs(v,i);
		f[u][0]+=max(f[v][0],f[v][1]);
		f[u][1]+=f[v][0];
	}
	return f[u][0];
}
int main(){
	scanf("%d",&n);
	for(int v=1,u;v<=n;v++){
		scanf("%d %d",&w[v],&u);
		adde(u,v);adde(v,u);
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			r1=r2=0;
			findd(i,0);
			if(r1){
				LL res1=dfs(r1,0);
				LL res2=dfs(r2,0);
				sum+=max(res1,res2);
			}
			
		}
	}
	printf("%lld\n",sum);
	return 0;
}

  

标签:rt,head,int,LL,基环树,maxn,include
From: https://www.cnblogs.com/shirlybaby/p/17393824.html

相关文章

  • U259394 Gmt丶FFF 的基环树 题解
    题目链接:传送门之所以评黑,是因为实在是太难调了。(又回调了)。对于有$40%$的数据,$n\le3000$,这部分我们可以暴力删边,然后暴力求直径即可。那么对于$100%$的数据:首先......
  • 基环树学习笔记
    基环树以下内容参考:https://www.cnblogs.com/fusiwei/p/13815549.html概念基环树也叫环套树,标准定义是一个有\(n\)个节点\(n\)条边的联通图,如果不是联通的,则称其是......
  • 基环树
    基环树知识点来自:基环树1.基环树众所周知树的性质,即对于一个有\(n\)个节点的树,必定保证有\(n−1\)条边(无向边)。反过来,对于一个由\(n−1\)条无向边组成的连通图,必......
  • Luogu P1453 城市环路(基环树DP)
    法一:dsu#include<bits/stdc++.h>usingll=longlong;usingnamespacestd;constintN=100010;structnode{intv,nxt;}e[N......
  • 基环树专题
    最近做了下题,作业题目有一道很有意思的题目[CF711D](https://codeforces.com/problemset/problem/711/D) 这道题问的是给出一个必存在至少一个环的图里面,每次操作可以......
  • 【XSY3326】米缸(时间复杂度均衡,线段树,基环树,倍增)
    时间复杂度的均衡。先考虑暴力的想法:显然这是一棵基环树,那么我们每次修改时暴力\(O(nm)\)重构基环树,然后询问的时候就能\(O(1)\)查询。时间复杂度\(O(nmq)\)。考虑......
  • 【ARC083F】Collecting Balls(图论模型,二分图,基环树,拓扑序)
    首先用\(2n\)个点表示每个机器人,原图中的一个球转化为图上的一条边,于是转化为一个二分图模型。我们对这个二分图的每个连通块分开考虑(假设有\(cnt\)个连通块),显然一个......
  • 做题记录整理图论/基环树/树上dp P1453 城市环路(2022/10/19)
    P1453城市环路本质上其实就是一个基环树上的没有上司的舞会但是由于太蒻了第一次接触。。。还是看了题解https://www.luogu.com.cn/blog/Zctoylm/solution-p1453#inc......
  • 【Coel.学习笔记】基环树动态规划
    引入基环树(又称环套树)是一种特殊的图,在原有的树形结构上添加一条边,就会形成一个环,看起来就像从环延伸出树。特别地,对于有向图而言,环上点所连接的边指向环外为外向树,反之为......
  • Luogu2607 & Luogu1453 基环树dp
    2607:一个基环树,有点权,全是有向边,选儿子则不能选父亲(反之亦然),问选出的集合的最大点权和注意到题目的特殊性,如果i->hatred[i],那么就是一个内向树,否则为外向树内向树好找环,......