POJ_2186_Popular Cows_强连通分量
Popular Cows
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 30680 | Accepted: 12445 |
Description
Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.
Input
* Line 1: Two space-separated integers, N and M
* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.
* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.
Output
* Line 1: A single integer that is the number of cows who are considered popular by every other cow.
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
大意:n只牛,m对数(a,b)表示a认为b牛逼。若a认为b牛逼,b认为c牛逼,那么a也认为c牛逼。问n只牛中,有多少只牛是其他所有牛都认为牛逼的。
分析:若图为不连通,则答案为0.当图连通时,在同一个强连通分量A中的牛在被该强连通分量中其他牛认为牛逼;若在A和另一个强连通分量B之间有路,假设A指向B,则A中的牛都认为B中的牛是牛逼的。任意一个有向图都可以分解成若干不相交的强连通分量,把每个强连通分量缩点,就得到一个DAG(有向无环图)。该题要找的是缩点后DAG中出度为0的点所表示的强连通分量中的点数。(该出度为0的点一定唯一,否则不可能有其他牛都认为牛逼的牛)
求强连通分量可使用tarjan算法。
当DFN(u)=Low(u)时,以u为根的搜索子树上所有节点是一个强连通分量。
void tarjan(int s) { vis[s]=2; dfn[s]=low[s]=++now; sta.push(s); for(int i=0; i<gra[s].size(); i++) { int t=gra[s][i]; if(dfn[t]==0) { tarjan(t); low[s]=min(low[s],low[t]); } else if(vis[t]==2) low[s]=min(low[s],dfn[t]); } if(low[s]==dfn[s]) { sum++; while(!sta.empty()) { int t=sta.top(); sta.pop(); vis[t]=1; num[t]=sum; if(t==s) break; } } }
AC代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stdlib.h> #include<vector> #include<stack> using namespace std; #define LL long long #define N 10005 vector<int> gra[N]; stack<int>sta; int n,m,dfn[N],low[N],vis[N],num[N]; int degree[N],sum,now,res,loc; void init() { sum=0; now=0; res=0; memset(vis,0,sizeof(vis)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(degree,0,sizeof(degree)); for(int i=0; i<=n; i++) gra[i].clear(); while(!sta.empty()) sta.pop(); } void read() { int a,b; scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { scanf("%d%d",&a,&b); gra[a].push_back(b); } } void tarjan(int s) { vis[s]=2; dfn[s]=low[s]=++now; sta.push(s); for(int i=0; i<gra[s].size(); i++) { int t=gra[s][i]; if(dfn[t]==0) { tarjan(t); low[s]=min(low[s],low[t]); } else if(vis[t]==2) low[s]=min(low[s],dfn[t]); } if(low[s]==dfn[s]) { sum++; while(!sta.empty()) { int t=sta.top(); sta.pop(); vis[t]=1; num[t]=sum; //缩点 if(t==s) break; } } } void solve() { for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i); for(int i=1; i<=n; i++) for(int j=0; j<gra[i].size(); j++) if(num[i]!=num[gra[i][j]]) degree[num[i]]++; //对缩点后的DAG进行出度的统计 for(int i=1; i<=sum; i++) { if(degree[i]==0) { res++; loc=i; //第几个强连通分量 } } if(res>1) printf("0\n"); else { res=0; for(int i=1; i<=n; i++) if(num[i]==loc) res++; printf("%d\n",res); } } int main() { init(); read(); solve(); return 0; } /* 3 3 1 2 2 1 2 3 */
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· 趁着过年的时候手搓了一个低代码框架
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现