首页 > 其他分享 >tarjan、缩点、删点、删边

tarjan、缩点、删点、删边

时间:2023-10-26 17:46:49浏览次数:39  
标签:缩点 tarjan int top ++ low 删点 sum

D. Cyclic Operations

好久没有用 tarjan 了,今天做一道题,顺便复习一下

tarjan 是用来求连通性的算法,时间复杂度 O(n)。网上关于 tarjan 的博文很多,我这里就不写了,只是复习一下。

这道题很容易想到建边 i-a[i]:

对于长度是 k 的环,很显然可以满足;

对于长度不是 k 的环,无论如何都不能满足;

对于不构成环的点,可以随意向环中的点借位,因为不构成环,所以彼此互不影响,被借位的环中的点最后覆盖即可。

上代码:

#include<bits/stdc++.h>
#define inf 1000000000
#define mod 998244353
using namespace std;
const int N=1e6+10;
int n,m,t,k,qq,tot,deep,sum,top;
int f[N],dp[N],a[N],h[N],H[N],num[N];
int dfn[N],low[N],vis[N],Stack[N],color[N],cnt[N];
vector<int>e[N];
void tarjan(int u){
    dfn[u]=low[u]=++deep;
    vis[u]=1;
    Stack[++top]=u;
    for(int v:e[u]){
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v]) low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        color[u]=++sum;
        vis[u]=0;num[sum]++;
        while(Stack[top]!=u){
            num[sum]++;
            color[Stack[top]]=sum;
            vis[Stack[top--]]=0;
        }
        --top;
    }
}
void init(){

}
void solve(){
    cin>>n>>k;
    for(int i=1;i<=2*n;++i) dfn[i]=vis[i]=color[i]=num[i]=low[i]=Stack[i]=0;
    for(int i=1;i<=n*2;++i) e[i].clear();
    deep=top=0;
    for(int i=1;i<=n;++i) cin>>a[i],e[i].push_back(a[i]);
    if(k==1){
        for(int i=1;i<=n;++i){
            if(a[i]!=i){ cout<<"NO"<<endl;return; }
        }
        cout<<"YES"<<endl;
    }
    else{
        for(int i=1;i<=n;++i){
            if(a[i]==i){ cout<<"NO"<<endl;return; }
        }
        for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
        for(int i=1;i<=n;++i){
            if(num[color[i]]!=k&&num[color[i]]!=1){
                cout<<"NO"<<endl;return;
            }
        }
        cout<<"YES"<<endl;
    }
}
signed main(){
    int T=1;
    cin>>T;
    init();
    while(T--) solve();
    return 0;
}

 

标签:缩点,tarjan,int,top,++,low,删点,sum
From: https://www.cnblogs.com/buleeyes/p/17789943.html

相关文章

  • TARJAN复习 求强连通分量、割点、桥
    TARJAN复习求强连通分量、割点、桥目录TARJAN复习求强连通分量、割点、桥强连通分量缩点桥割点感觉之前写的不好,再水一篇博客强连通分量“有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(......
  • 连通性与 Tarjan
    强连通分量和Tarjan强连通分量(StronglyConnectedComponents,SCC),指的是极大的连通子图。tarjan算法,用于求图的强连通分量。dfs生成树有向图的dfs生成树大致分为四种边:树边(treeedge):示意图中以黑色边表示,每次搜索找到一个还没有访问过的结点的时候就形成了一条树边......
  • Tarjan强连通分量详解
    1、简介:在阅读下列内容之前,请务必了解 图论相关概念 中的基础部分。强连通的定义是:有向图G强连通是指,G中任意两个结点连通。强连通分量(StronglyConnectedComponents,SCC)的定义是:极大的强连通子图。这里要介绍的是如何来求强连通分量。2、引入:在介绍该算法之前,先来了解......
  • [学习笔记] Tarjan 连通性全家桶
    拜谢陈老师的PPT!!!无向图割点若点\(x\)不为搜索树的根节点,则\(x\)是割点当且仅当搜索树上存在一个\(x\)的子节点\(y\)满足:\(dfn_x\lelow_y\)。特别地,当\(x\)是搜索树的根节点时,则\(x\)是割点当且仅当有两个点\(y_1,y_2\)满足上述条件。割边边\((x,y)\)是......
  • luogu P4819 [中山市选] 杀人游戏 题解 【强连通分量+缩点】
    目录题目链接思路分析代码题目链接P4819思路分析首先考虑这道题的连通性。容易发现这种类型的题目会容易产生环形的状态转移。假设我们知道了其中的一个点是否是黑白点,那么我们就可以知道所有点是否是黑白点。容易陷入一个误区:我们只能通过一个点知道他所相邻的最直接的点,如何......
  • tarjan学习笔记
    tarjan学习笔记0.前置知识强连通图在一个有向图中,若从任意一点可以到达其他所有点,则称之为强连通图强连通分量(SCC)一个图中的极大强连通性质子图(强连通图的强连通分量是它本身)\(\small{极大强连通子图指一个不能加入另外的点的强连通子图(一个强连通子图可能包含一个或多......
  • 最近公共祖先 Tarjan算法
    P3379【模板】最近公共祖先(LCA)利用并查集点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=5e5+10;vector<int>g[N];vector<pair<int,int>>query[N];intans[N],vis[N];intf[N];intfind(intx){ returnf[x]==x?x:f[x]......
  • Tarjan
    无向图的割点先给出几个定理:A:一棵树中的所有结点对于任意结点的可达性一致。记\(p(u,v)表示u和v可以相互到达\)。也就是说,如果G是一棵树,那么\(\forallu,v\inG,\forallk,p(u,k)\iffp(k,u)\)。B:一个无向图的DFS树中,对于任意一个非树边\((u,v)\),\(u,v\)一定有祖先孩......
  • tarjan 求强连通分量
    for(inti=0;i<n;i++)//图可能是不连通的,因此要表里每个点 if(!dfn[i]) tarjan(i);voidtarjan(intu){ inti,v; dfn[u]=low[u]=ntime++; z.push(u); f[u]=1; for(i=0;i<q[u].size();i++){ v=q[u][i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]);......
  • tarjan强连通分量
    intscc[N],sc;//结点i所在scc的编号intsz[N]; //强连通i的大小//dfn(u)为搜到结点u时的次序编号//low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号//当dfn(u)=low(u)时,以u为根的搜索子树上的所有节点是一个强连通分量voidtarjan(intu){ dfn[u]=low[u]......