[HAOI2006]受欢迎的牛---强连通分量加缩点
作者:互联网
题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶
牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜
欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你
算出有多少头奶牛可以当明星。
输入格式:
第一行:两个用空格分开的整数:N和M
第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B
输出格式:
第一行:单独一个整数,表示明星奶牛的数量
输入样例
3 3
1 2
2 1
2 3
输出样例
1
简单地讲一下思路
这道题目的是让我们找被其他所有奶牛所欢迎的奶牛数量,我当时很奇怪,被除自己一外的牛都喜欢,不是肯定只有一个吗?然后我反应过来了,一个可以看出强连通分量的缩点,也就是说找那个可以被其他所有强连通分量通向的那个强连通分量,也就是只有入度没有出度的那个强连通分量。
如果缩点不会强连通------tarjan算法详解及与缩点联合运用可以参考一下
通过给每一个出度不为零的强连通分量赋值为1,剩下为零的就是只有入度没有出度的那个强连通分量。
这里需要判断如果图本身有多个为零的强连通,就说明没有一个强连通分量被其他所有强连通分量都喜欢。
#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn=1e4+3;
int n,m,flag,cnt,low[maxn],dfn[maxn],vis[maxn],tar[maxn],ru[maxn];
vector<int> vec[maxn];
stack<int> sta;
void tarjan(int x)
{
vis[x]=1;
low[x]=dfn[x]=++cnt;
sta.push(x);
for(int i=0;i<vec[x].size();i++)
{
int to=vec[x][i];
if(!dfn[to])
{
tarjan(to);
low[x]=min(low[x],low[to]);
}
else if(vis[x])
low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x])
{
flag++;
int z;
while(sta.top()!=x)
{
z=sta.top();
sta.pop();
vis[z]=0;
tar[z]=flag;
}
z=sta.top();
sta.pop();
vis[z]=0;
tar[z]=flag;
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
vec[x].push_back(y);
}
flag=0;
cnt=0;
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
{
for(int j=0;j<vec[i].size();j++)
{
int to=vec[i][j];
if(tar[i]!=tar[to])
ru[tar[i]]=1;
}
}
int p,flag1=0;
for(int i=1;i<=flag;i++)
{
if(ru[i]==0)
{
p=i;
flag1++;
}
}
if(flag1>1)
{
cout<<"0";
}
else{
int summ=0;
for(int i=1;i<=n;i++)
{
if(tar[i]==p)
{
summ++;
}
}
cout<<summ; }
return 0;
}
青云66
发布了25 篇原创文章 · 获赞 3 · 访问量 519
私信
关注
标签:加缩点,连通,include,int,HAOI2006,maxn,奶牛,分量 来源: https://blog.csdn.net/qq_44162236/article/details/104074971