栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

图论洛谷简单习题

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

图论洛谷简单习题

文章目录

并查集

并查集
//此处优化为更新x的祖先时顺便更新了x父亲的祖先也为x的祖先
int ff(x){return fa[x]==x?x:fa[x]=ff(fa[x]);}
int join(int x,int y){x=ff(x),y=ff(y);x=fa[y];}

P2661 [NOIP2015 提高组] 信息传递
用并查集难的地方是在寻找父亲和合并过程的变化。要了解合并和寻找过程对题目变量的影响。
一旦 i i i查询的 x x x和 i i i不是直接父子关系,继续向上查找合并就应该算成另外一轮,并且是当前轮之前的轮数确定的并集关系。
同时模板中查找父亲时顺便更新父亲的祖先的优化也不能加入,因为这个优化的作用在于将 x x x并查集内的所有节点都变成 x x x祖先的直接后继,将整个并集变成二层结构,从而减少 x x x的父亲查找其祖先的次数,但是这个次数恰恰是我们需要的轮数。

#include
using namespace std;
const int N=200007;
int fa[N],n,ans=0x3f3f3f3f,cnt;
int ff(int x){
    cnt++;
    return fa[x]==x?x:ff(fa[x]);
}
int  main(){
    cin>>n;
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=n;i++){
        cnt=0;
        int x;cin>>x;
        if(ff(x)!=i){
            fa[i]=x;
        }
        else ans=min(cnt,ans);
    }
    cout< 

P1525 [NOIP2010 提高组] 关押罪犯
敌人的敌人是朋友,只要保存当前边的两个人原先有的敌人,再交叉将对方与自己的敌人合在一个并查集即可。这个题很像食物链,就是在扩展空间保存不同关系。

#include
using namespace std;
const int N=2e4+7,M=1e5+7;
int n,m;
struct Peo{
    int fa,enemy;
}peo[N];
struct Node{
    int u,v,w;
    bool operator<(const Node &a){return w>a.w;}
}node[M];
int ff(int x){return peo[x].fa==x?x:peo[x].fa=ff(peo[x].fa);}
int join(int x,int y){x=ff(x),y=ff(y);peo[x].fa=y;}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)peo[i].fa=i;
    for(int i=1;i<=m;i++)cin>>node[i].u>>node[i].v>>node[i].w;
    sort(node+1,node+1+m);
    for(int i=1;i<=m;i++){
        int u=node[i].u,v=node[i].v;
        if(ff(u)==ff(v)){
            cout< 

P1197 [JSOI2008]星球大战
先将所有的连边存储起来,按顺序保存每个要炸毁的点,再连接那些不被炸毁的边,此时的连通块个数就是炸毁 k k k个点之后的连通块个数,相当于是最后的连通块个数,因此用栈来存储答案。接下来逆序遍历 k k k个要炸毁的点,每次添加一个点及其连边。每次连边都是将两个连通块变成一个,因此连通块总个数减少1。

#include
using namespace std;
const int N=4e5+7,M=2e5+7;
vectorson[N];
int fa[N],n,m,k,broken[N],stk[N],top;
bool vis[N];
int ff(int x){return fa[x]==x?x:fa[x]=ff(fa[x]);}
int main(){
    cin>>n>>m;
    for(int i=0;i>u>>v;
        son[u].push_back(v);son[v].push_back(u);
    }
    cin>>k;
    int cnt=n-k;

    for(int i=1;i<=k;i++){
        cin>>broken[i];
        vis[broken[i]]=true;
    }
    for(int u=0;u
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/744257.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号