2186 – Popular Cows
Language:
Popular Cows
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 29300 Accepted: 11850
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.
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.
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
Hint
Cow 3 is the only cow of high popularity.
Source
USACO 2003 Fall
一只奶牛,之间有互相仰慕的关系,如果A仰慕B,B仰慕C,意味着A也仰慕C,问有多少奶牛被所有奶牛仰慕。仰慕关系是有向的,先进行强连通缩点,缩完点之后形成DAG,如果不完全连通,那么没有答案。否则被所有奶牛仰慕的奶牛,必然是在DAG中出度为0的结点中,并且该结点的强连通分量个数为1。
我的代码里是先跑一遍tarjan,belong数组里面存的是一个点属于哪个连通分量。在这基础上建树也就是上面说的哪个DAG,接下来用上面的那个条件判断一波就可以了。
#include "cstring"
#include "cstdio"
#include "iostream"
using namespace std;
#define V 10005
#define E 50005
struct edge
{
int to, next;
}Edge[E],newEdge[E];
int head[V], e, n;
int newhead[V];
int indeg[V], outdeg[V]; //点的入度和出度数
int belong[V], low[V], dfn[V], scc, cnt;//dfn[]:遍历到u点的时间; low[]:u点可到达的各点中最小的dfn[v]
int S[V], top;
bool vis[V];//v是否在栈中
int addedge(int u, int v)
{
Edge[e].to = v;
Edge[e].next = head[u];
head[u] = e++;
return 0;
}
int newaddedge(int u, int v)
{
newEdge[e].to = v;
newEdge[e].next = newhead[u];
newhead[u] = e++;
return 0;
}void tarjan(int u)
{
int v;
dfn[u] = low[u] = ++cnt;//开始时dfn[u] == low[u]
S[top++] = u;//不管三七二十一进栈
vis[u] = true;
for (int i=head[u]; i!=-1; i=Edge[i].next)
{
v = Edge[i].to;
if (dfn[v] == 0)//如果v点还未遍历
{
tarjan(v);//向下遍历
low[u] = low[u] < low[v] ? low[u] : low[v];//确保low[u]最小
}
else if (vis[v] && low[u] > dfn[v])//v在栈中,修改low[u]
low[u] = dfn[v];
}
if (dfn[u] == low[u])//u为该强连通分量中遍历所成树的根
{
++scc;//缩点后点的编号是从1开始的
do
{
v = S[--top];//栈中所有到u的点都属于该强连通分量,退栈
vis[v] = false;
belong[v] = scc;
} while (u != v);//????????
}
}
int solve()
{
scc = top = cnt = 0;
memset(dfn, 0, sizeof(dfn));
memset(vis, false, sizeof(vis));
for (int u=1; u<=n; ++u)
if (dfn[u] == 0)
tarjan(u);
return scc;
}
int cntfenliang[V];
void count_deg()
{
memset(indeg, 0, sizeof(indeg));
memset(outdeg, 0, sizeof(outdeg));
for (int u=1; u<=n; ++u)
for (int i=head[u]; i!=-1; i=Edge[i].next)
{
int v = Edge[i].to;
if (belong[u] != belong[v])
{
indeg[belong[v]]++;
outdeg[belong[u]]++;
}
}
}
int main()
{
int m;
while (~scanf("%d%d", &n,&m))
{
e = 0;
int u,v;
memset(head, -1, sizeof(head));
for (int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
addedge(u, v);
}
int scc=solve();
count_deg();
//计算一个强联通分量里有几个点
memset(cntfenliang,0,sizeof(cntfenliang));
for(int i=1;i<=n;i++)
cntfenliang[belong[i]]++;
//遍历原图建新图
memset(newhead,-1,sizeof(newhead));
e=0;
for(int j=1;j<=n;j++)
{
for(int i=head[j];i!=-1;i=Edge[i].next)
{
int temp=Edge[j].to;
if (belong[j] != belong[temp])
{
newaddedge(belong[j],belong[temp]);
}
}
}
int outc=0;
int a;
int cnt0=0;
for (int i=1; i<=scc; ++i)
{
if (outdeg[i] == 0)
{
outc++;
a=i;
}
}
if(outc==1)
{
printf("%d\n",cntfenliang[a]);
}
else
printf("0\n");
}
}
本文深入探讨了网络架构与数据处理技术的核心概念,包括云计算、人工智能、区块链等领域的最新发展。通过详细解释各种关键技术,如云计算平台、深度学习模型、智能合约和隐私计算,读者可以全面了解这些技术如何推动现代信息技术的进步。文章还讨论了数据安全、文档协作与知识管理等实际应用案例,提供了一系列实用的解决方案。
1335

被折叠的 条评论
为什么被折叠?



