首页 > 其他分享 >P2341 受欢迎的牛 G 题解

P2341 受欢迎的牛 G 题解

时间:2023-12-11 16:22:47浏览次数:39  
标签:cnt vector int 题解 st dfn P2341 受欢迎 奶牛

Link

P2341 [USACO03FALL / HAOI2006] 受欢迎的牛 G

Question

牛栏中有 \(N\) 头奶牛,和一些 \(M\) 对爱慕关系,A->B 表示 A 爱慕 B。每个奶牛都喜欢自己,被所有奶牛喜欢就是一头明星奶牛,求明星奶牛的数量

Solution

考虑一个强连通分量里面的奶牛是相互爱慕的,先根据强连通分量缩点,缩点之后就不会有奶牛的相互爱慕的。那么缩点后出度为 \(0\) 的奶牛就是明星奶牛

Code

#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
int cnt;
vector<vector<int> > E;
struct Tarjan{
    int n;
    vector<int>dfn,low;int dfn_cnt;
    vector<int> scc;int sc; //节点 i 所在 SCC 的编号
    vector<int> siz; //强连通 i 的大小
    stack<int> st;
    vector<int> in_st;//判断是否在栈内

    void init(int n){
        this->n=n;
        dfn.resize(n+1);low.resize(n+1);dfn_cnt=0;
        scc.assign(n+1,0);sc=0;siz.assign(n+1,0);
        while(!st.empty())st.pop();
        in_st.assign(n+1,0);
    }

    void tarjan(int u){
        low[u]=dfn[u]=++dfn_cnt;st.push(u);in_st[u]=1;
        for(int i=0;i<E[u].size();i++){
            int& v=E[u][i];
            if(!dfn[v]){//没有访问过
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(in_st[v]){
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u]){ //找到双连通分量了
            ++sc; 
            while(st.top()!=u){ //从栈顶到 u 都是这个强连通分量里面的
                scc[st.top()]=sc;siz[sc]++;
                in_st[st.top()]=0;st.pop();
            }
            scc[st.top()]=sc;siz[sc]++;
            in_st[st.top()]=0;st.pop();
        }
        return ;
    }
};
int main(){
    scanf("%d %d\n",&n,&m);
    E.resize(n+1);
    for(auto& e:E) e.clear();
    for(int i=1;i<=m;i++){
        int x,y;scanf("%d%d",&x,&y);
        E[x].push_back(y);
    }

    Tarjan F;F.init(n);
    for(int i=1;i<=n;i++) if(!F.dfn[i])
        F.tarjan(i);

    vector<int> du(n+1,0);
    for(int u=1;u<=n;u++)
        for(int& v:E[u]){
            if(F.scc[u]!=F.scc[v]){
                du[F.scc[u]]++;
            }
        }
    for(int i=1;i<=F.sc;i++)
        if(du[i]==0){
            cnt++;
            ans+=F.siz[i];
        }
    if(cnt==1) printf("%d\n",ans);
    else printf("0\n");
    return 0;
}

标签:cnt,vector,int,题解,st,dfn,P2341,受欢迎,奶牛
From: https://www.cnblogs.com/martian148/p/17894708.html

相关文章

  • 题解 QOJ1173【Knowledge Is...】 / accoders::NOI 5681【interval】
    https://qoj.ac/contest/537/problem/1173problem给定\(n\leq10^6\)个区间,你需要求出能够最多选出多少对区间,使得两个区间不交(区间为闭区间)。要求一个区间最多属于一对选出的区间。solution这是一般图匹配问题的特殊情况,所以放弃dp,考虑贪心、网络流、匹配等。按照左端点......
  • P5048 [Ynoi2019 模拟赛] 题解
    题意给定\(n\)个数,有\(m\)个询问,每个询问给定\(l\)和\(r\),求出区间\(l\)到\(r\)中的最小众数出现次数,强制在线。数据范围:\(n\le500000\),空间限制:\(62.5MB\)。思路这道题的弱化版是蒲公英,这道题加强的地方在于数据范围。正常的分块求区间众数的空间复杂度是\(O(n......
  • CF1842E Tenzing and Triangle 题解
    题意不多赘述。思路如果两个所选的三角形有重合部分的话,那么这种情况肯定是不会出现的。因为如果把这两个三角形合成一个大三角形的话,不仅覆盖面积会增大,而且花费的代价还不会多。于是我们可以想到用dp来解决,设\(dp_{i}\)表示删完横坐标为\(0\)到\(i\)中的点的最小代价......
  • [ABC304Ex] Constrained Topological Sort 题解
    题意给定一张有向图\(G\),有\(n\)个点和\(m\)条边,问是否存在一种拓扑序的排列\(P\)使得\(l_{i}\lep_{i}\ler_{i}\)。思路首先对于一条边\(u\tov\),如果限制满足\(r_{v}\ler_{u}\)或者\(l_{v}\gel_{u}\)的话,那么这个限制其实是不完全正确的。因为最终的序列......
  • 【题解】AtCoder abc322_f Random Update Query
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_f容易发现,对于一个位置$i$,$A_i$的最终值是由对$i$的最后一次赋值操作决定的;因此,将所有操作按时间顺序倒过来考虑,则由第$j$次操作决定$A_i$最终值的概率为"在第$(j+1)$~$m$次操作中没有修改过$i$的概率"与"第......
  • 【题解】AtCoder abc332_g Not Too Many Balls
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_g看完题,第一眼反应为最大流。建模方式为:以颜色为左部点,盒子为右部点,源点$S$向颜色$i$连一条容量为$A_i$的边,盒子$j$向汇点$T$连一条容量为$B_j$的边,颜色$i$向盒子$j$连一条容量为$ij$的边;在这张图......
  • AT_cf17_final_j Tree MST 题解
    题意:给定一颗\(n\)个点的树,点\(i\)有权值\(a_{i}\),边有边权。现在有另外一个完全图,两点之间的边权为树上两点之间的距离加上树上两点的点权,求这张完全图的最小生成树。首先有一个很显然的暴力,把完全图中每两点之间的边权算出来,然后跑一边最小生成树,时间复杂度\(O(n^{2}\lo......
  • P7735 [NOI2021] 轻重边 题解
    是一道树剖好题,之前听lsl讲过一点,于是很快就做出来了。题意:有一个\(n\)个节点的树,最开始的时候所有边都是轻边,维护两个操作:操作一:将\(u\)到\(v\)的路径中经过的所有点的邻边变为轻边,再将这条路径上的边变为重边。操作二:求出\(u\)到\(v\)这条路径上有多少条重边......
  • 小程序建立用户与数据的联系问题解决方案
    在小程序中建立用户与数据的联系是一个常见的问题,在本文中提供了一个解决方案。这个解决方案包括几个关键步骤。首先,需要通过用户登录功能实现用户的身份识别,并获取到用户的唯一标识符。接着,需要在后台数据库中创建一个用户表,用于存储用户的基本信息和与之相关联的数据。在这个表中......
  • ARC169 B Subsegments with Small Sums 题解
    LinkARC169BSubsegmentswithSmallSumsQuestion\(x\)是一个序列,定义\(f(x)\)为把序列\(x\)切成几段,每段的和不能超过\(S\)的最小段数给出序列\(A=(A_1,A_2,\cdots,A_N)\)求:\[\sum_{1\lel\leN}f((A_l,A_{l+1},\cdots,A_r))\]Question先考虑一个结论,\(x\)为......