首页 > 其他分享 >洛谷P2341/USACO03FALL 受欢迎的牛

洛谷P2341/USACO03FALL 受欢迎的牛

时间:2023-02-19 21:36:31浏览次数:51  
标签:缩点 洛谷 int scc MAXN P2341 USACO03FALL 奶牛 low

题意分析

题目链接
喜欢是单向的,喜欢有传递性……Emmm这听起来好像……对了,就是连通性问题
我们不妨将奶牛之间的喜欢关系表示为一条条单向边,怎么求明星奶牛的数量呢?
这里我们提出一个概念,缩点

设计算法

缩点是什么呢,它将环处理为点的一种方式,因为我们可以想想,如果一群奶牛呈这样的喜欢模式:
在这里插入图片描述
这时候不难发现其实它们可以变为一个点,因为它们之中任意一个点与其他点发生喜欢或被喜欢关系,都会在它们之中传递,呈强连通关系。因此我们只需要把它们视作一个点即可,只是如果这个“点”成为了明星奶牛,不能只按一只明星奶牛计算,而要在缩点时记录下这个”点“实际的奶牛数量


那么假如说我们缩完点后,如何寻找明星奶牛呢?
举个栗子
如果原来的图长这个样子:
在这里插入图片描述
那么缩点后的图就长这个样子:
在这里插入图片描述
很明显明星奶牛为节点6,展开该节点发现共有3头明星奶牛
因此,重点来了!,我们可以看出此题缩点的妙处!
因为我们已经缩点了,所以图内没有任何强连通分量了,所以构成了一个层层递进,最终归于汇点的体系,那么汇点就是明星奶牛,所谓汇点,在图中,不就是出度为0的点吗
但是,一些逻辑缜密的读者也许已经看出来了,还存在一点问题……


我们稍微做一点变动:
在这里插入图片描述
请问,在此时,还存在明星奶牛吗?显然由于加入的7谁都不喜欢,与6互不相让,最终两败俱伤,不存在任何明星奶牛
因此,我们还要对刚才做的结论进行一点修正

缩点后,若只存在一个出度为0的点,该点(或点展开后的所有奶牛)为明星奶牛,否则不存在明星奶牛

代码实现

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e4+5;
int n,m,cnt=0,scc_num/*总共强连通分量的个数*/,dfn[MAXN],low[MAXN],out_deg[MAXN]/*出度*/,fa[MAXN],scc[MAXN];
//注意scc数组存的是节点所在scc的节点个数,fa才是节点所在的scc编号
bool instack[MAXN];//是否在栈中
vector<int>g[MAXN];//我用的是链表存图
stack<int>s;
void tarjan(int x){
    dfn[x]=low[x]=++cnt;
    s.push(x);instack[x]=1;
    for(auto it:g[x]){
        if(!dfn[it]){
            tarjan(it);
            low[x]=min(low[x],low[it]);
        }
        else if(instack[x]) low[x]=min(low[x],dfn[it]);
    }
    if(low[x]==dfn[x]){//找完了一个强连通
        scc_num++;
        int cur;
        do{
            cur=s.top();s.pop();
            instack[cur]=0;
            fa[cur]=scc_num;
            scc[scc_num]++;
        }while(cur!=x);
    }
}
int main(){
    memset(scc,0,sizeof(scc));
    memset(instack,0,sizeof(instack));
    memset(out_deg,0,sizeof(out_deg));
    cin>>n>>m;
    int a,b;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        g[a].push_back(b);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]) tarjan(i);
    }
    //求强连通分量↑
    for(int i=1;i<=n;i++){//由于我们只需要缩点后各个点的出度,所以不需要真的把图重构一遍,但是注意不是所有题都是这样
        for(auto it:g[i]){
            if(fa[i]!=fa[it]) out_deg[fa[i]]++;
        }
    }
    //缩点↑
    int scc_cnt=0,ans;
    for(int i=1;i<=scc_num;i++){
        if(out_deg[i]==0){
            scc_cnt++;
            ans+=scc[i];//缩点展开
        }
    }
    if(scc_cnt==1) cout<<ans<<endl;
    else cout<<0<<endl;//不存在明星奶牛
    return 0;
}

标签:缩点,洛谷,int,scc,MAXN,P2341,USACO03FALL,奶牛,low
From: https://www.cnblogs.com/SkyNet-PKN/p/17135639.html

相关文章

  • 洛谷P3694 邦邦的大合唱站队
    题目分析首先我们来抓题目里的关键信息:最少、M≤20那么由此得出做法就是DFS、贪心或DP,我们一一讨论DFS暴搜复杂度\(O(m!)\),只能过70%(70%它不香吗)贪心如果要贪心我......
  • [洛谷P3959][NOIP2017提高组] 宝藏
    [NOIP2017提高组]宝藏题目描述参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了\(n\)个深埋在地下的宝藏屋,也给出了这\(n\)个宝藏屋之间可供开发的\(m\)条道......
  • [洛谷P5368] 真实排名
    [PKUSC2018]真实排名题目描述小C是某知名比赛的组织者,该比赛一共有\(n\)名选手参加,每个选手的成绩是一个非负整数,定义一个选手的排名是:成绩不小于他的选手的数量(包括......
  • 洛谷 P1223 排队接水
    原题链接题解C++存在一种pair类型,并且可以指定first/second的数据类型,所以可以使用它来代替只有两个元素的结构体利用sort对数据进行排序,将取水时间从小到大排序为什......
  • 洛谷 P2240 部分背包问题
    原题链接题解这道题是贪心只要按照性价比最高的取一定得到的价值最大性价比就是这堆金币的价值除以重量只需要把这些金币按性价比排序就行了最后在超出和未超出之间......
  • 洛谷 P2014 选课 树形依赖背包
    题目描述在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有N门功......
  • 树形DP依赖背包 洛谷 P2015 二叉苹果树
    题目描述有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。我们用一根树枝两端连接的......
  • 种类并查集 洛谷 P2024 食物链
    题目描述动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B,B吃C,C吃A。现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道......
  • POJ 3276 Face The Right Way/洛谷P2882 [USACO07MAR]面对正确的方式 反转
    题目描述FarmerJohnhasarrangedhisN(1≤N≤5,000)cowsinarowandmanyofthemarefacingforward,likegoodcows.Someofthemarefacingbackward,th......
  • 洛谷 P2412 查单词
    这是一个非常有意思的题……这一个题放在线段树里面显得非常清奇。很多题解并没有用线段树,或者是用的线段树方法很难。因此,这里为初学者献上一份较为简单容易看懂的代码。......