【图论】拓扑排序

模板 B3644

BFS

cpp 复制代码
const int N=2e5+10,mod=998244353,M=2e5+10;
int n,m;
vector<int>v[N],tp;
int din[N];
void toposort(){
    queue<int>q;
    forr(i,1,n)
        if(din[i]==0)q.push(i);
    while (q.size())
    {
        int x=q.front();
        tp.push_back(x);
        q.pop();
        for(auto i:v[x]){
            if(--din[i]==0)q.push(i);//把入度为0的点都放进q等待遍历
        }
    }
}
void solve(){
    cin>>n;
    forr(i,1,n){
        int a;
        while (cin>>a&&a){
            v[i].push_back(a);
            din[a]++;
        }
    }
    toposort();
    for(auto i:tp)cout<<i<<' ';
}

DFS

cpp 复制代码
int n,m;
vector<int>v[N],tp;
int c[N];
void dfs(int x){
    c[x]=-1;//在路上的都赋值
    for(auto i:v[x]){
        if(c[i]==0)dfs(i);//进入还没走过的路径
    }
    c[x]=1;//走完的记录
    tp.push_back(x);
    return;
}
void toposort(){
    memset(c,0,sizeof c);
    forr(i,1,n){
        if(c[i]==0)dfs(i);
        for(auto i:tp)cout<<i<<' ';cout<<endl;
    }
    reverse(tp.begin(),tp.end());//dfs 先返回的是儿子节点 最后要逆转
}
void solve(){
    cin>>n;
    forr(i,1,n){
        int a;
        while (cin>>a&&a){
            v[i].push_back(a);
        }
    }
    toposort();
    for(auto i:tp)cout<<i<<' ';
}

把题意抽象成图

P4089

每个点只有一个出度

cpp 复制代码
int n;
vector<int>tp;//存所有入度为0的点,不成环
int din[N],a[N];
void bfs(){
    queue<int>q;
    forr(i,1,n)
        if(din[i]==0)q.push(i);
    while (q.size())
    {
        int x=q.front();
        tp.push_back(x);
        q.pop();
        if(--din[a[x]]==0)q.push(a[x]);//把入度为0的点都放进q等待遍历
    }
}
void solve(){
    cin>>n;
    forr(i,1,n){
        cin>>a[i];
        din[a[i]]++;
    }
    bfs();
    cout<<n-tp.size()<<endl;
}

GDCPC 2024 不等式

cpp 复制代码
const int N=2e5+10,mod=998244353,M=2e5+10;
struct pr
{
    int b,c;
};
int n,m;
int ans,sz;
set<int>v[N];
vector<pr>sm[N];
int din[N],val[N];

void toposort(){
    queue<int>q;
    forr(i,1,n)if(!din[i])q.push(i);
    while (q.size())
    {
        int x=q.front();
        q.pop();
        sz++;

        for(auto i:v[x]){
            if(--din[i]==0)q.push(i);
        }
        val[x]=1;
        for(auto i:sm[x]){
            val[x]=max(val[x],val[i.b]+val[i.c]);
        }
        ans+=val[x];
    }
    
}
void solve(){
    cin>>n>>m;
    forr(i,1,m){
        int x,y,z;
        cin>>x>>y>>z;
        sm[x].push_back({y,z});
        if(!v[y].count(x)){
            v[y].insert(x);
            din[x]++;
        }
        if(!v[z].count(x)){
            v[z].insert(x);
            din[x]++;
        }
    }
    toposort();
    cout<<(ans>1e9||sz<n?-1:ans)<<endl;
}

XJTUPC2024 雪中楼 把题意抽象成图

抽象成一个链表,矮的后继高的

给的 a i a_i ai比 i i i矮, a i → i a_i\rightarrow i ai→i

指向相同前驱的点,编号越小越高,把树变链表

cpp 复制代码
int n;
vector<int>v[N];
int a[N];
void bfs(){
    queue<int>q;
    forr(i,1,n)
        if(din[i]==0)q.push(i);
    while (q.size())
    {
        int x=q.front();
        tp.push_back(x);
        q.pop();
        if(--din[a[x]]==0)q.push(a[x]);//把入度为0的点都放进q等待遍历
    }
}
void solve(){
    cin>>n;
    forr(i,1,n){
        cin>>a[i];
        v[a[i]].push_back(i);//矮的指向高的
    }
    int nw=0;
    forr(i,1,n){//指向同一个点的 序号越小越高
        sort(v[nw].begin(),v[nw].end(),greater<int>());//z序号越小越高 序号从大到小
        while (v[nw].size()>1)//把高的都归位
        {
            int h=v[nw].back();v[nw].pop_back();
            int l=v[nw].back();
            v[l].push_back(h);
        }
        nw=v[nw].front();
    }
    nw=0;
    forr(i,1,n){
        if(v[nw].size()){
            cout<<v[nw].front()<<' ';
            nw=v[nw].front();
        }
    }

}

带权值遍历DAG

P1038 神经网络

cpp 复制代码
const int N=110,mod=998244353,M=2e5+10;
int n,m;
vector<int>v[N],e[N];
int din[N],dout[N],w[N][N],u[N],c[N];

void toposort(){
    queue<int>q;
    forr(i,1,n)if(!din[i])q.push(i);
    while (q.size())
    {
        int x=q.front();
        q.pop();
        int sm=0;
        for(auto j:v[x]){
            if(c[x]>0)c[j]+=w[x][j]*c[x];
            if(!--din[j])q.push(j);
        }

        
    }
}
void solve(){
    cin>>n>>m;
    forr(i,1,n){
        cin>>c[i]>>u[i];
        if(c[i]==0)c[i]-=u[i];
    }
    forr(i,1,m){
        int x,y,wv;
        cin>>x>>y>>wv;
        w[x][y]=wv;
        v[x].push_back(y);
        din[y]++,dout[x]++;
    }
    toposort();
    int fg=0;
    forr(i,1,n){
        if(!dout[i]&&c[i]>0)cout<<i<<' '<<c[i]<<endl,fg=1;
    }
    if(!fg)cout<<"NULL"<<endl;
}
相关推荐
艾莉丝努力练剑26 分钟前
【C语言16天强化训练】从基础入门到进阶:Day 7
java·c语言·学习·算法
地平线开发者1 小时前
LLM 中评价指标与训练概要介绍
算法·自动驾驶
Ghost-Face1 小时前
关于并查集
算法
zhangfeng11331 小时前
以下是基于图论的归一化切割(Normalized Cut)图像分割工具的完整实现,结合Tkinter界面设计及Python代码示
开发语言·python·图论
flashlight_hi2 小时前
LeetCode 分类刷题:2529. 正整数和负整数的最大计数
python·算法·leetcode
花火|2 小时前
算法训练营day60 图论⑩ Bellman_ford 队列优化算法、判断负权回路、单源有限最短路
算法·图论
2501_924890523 小时前
商超场景徘徊识别误报率↓79%!陌讯多模态时序融合算法落地优化
java·大数据·人工智能·深度学习·算法·目标检测·计算机视觉
艾醒3 小时前
大模型面试题剖析:模型微调和蒸馏核心技术拆解与考点梳理
算法
艾醒4 小时前
大模型面试题剖析:微调与 RAG 技术的选用逻辑
算法
NAGNIP4 小时前
一文弄懂MOE
算法