POJ 2186 Popular Cows
2014-01-22 22:34
288 查看
抽象成:在一个有向图中,找所有的点都可以到达的点的个数
根据题意结果必在一个强连通分量里(所有的答案之间肯定互相能到达)。用tarjan找出所有的连通分量,如果某个连通分量里有连到外面的边,则这个分量肯定不会是答案(分量图是有向的无环图,从分量1里连线到分量2中的边,分量2肯定没有变连回分量1,也就是1到达了2但是2不能到达1)。如果没有向外连边的连通分量不是1个就没有答案。
[Submit] [Go Back] [Status]
[Discuss]
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxV=11000,maxE=55000;
struct Edge
{
int to,next;
}edge[maxE];
int Adj[maxV],Size;
void init()
{
Size=0;
memset(Adj,-1,sizeof(Adj));
}
void Add_Edge(int u,int v)
{
edge[Size].to=v;
edge[Size].next=Adj[u];
Adj[u]=Size++;
}
int Low[maxV],DFN[maxV],Stack[maxV],Belong[maxV],num[maxV];
int Index,top,scc,n;
bool Instack[maxV];
void tarjan(int u)
{
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
for(int i=Adj[u];~i;i=edge[i].next)
{
v=edge[i].to;
if(!DFN[v])
{
tarjan(v);
Low[u]=min(Low[u],Low[v]);
}
else if(Instack[v])
{
Low[u]=min(Low[u],DFN[v]);
}
}
if(Low[u]==DFN[u])
{
scc++;
do
{
v=Stack[--top];
Instack[v]=false;
num[scc]++;
Belong[v]=scc;
}while(v!=u);
}
}
int solve(int n)
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
Index=scc=top=0;
for(int i=1;i<=n;i++)
{
if(!DFN[i]) tarjan(i);
}
return scc;
}
bool yes[maxV];
int main()
{
int m;
while(scanf("%d%d",&n,&m)!=EOF&&n)
{
init();
memset(yes,true,sizeof(yes));
int a,b;
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
Add_Edge(a,b);
}
int scc=solve(n);
for(int i=1;i<=n;i++)
{
for(int j=Adj[i];~j;j=edge[j].next)
{
int v=edge[j].to,u=i;
if(Belong[v]!=Belong[u])
{
yes[Belong[u]]=false;
}
}
}
int ans=0,tot=0;
for(int i=1;i<=scc;i++)
{
if(yes[i])
{
tot++;
ans+=num[i];
}
}
if(tot!=1) ans=0;
printf("%d\n",ans);
}
return 0;
}
根据题意结果必在一个强连通分量里(所有的答案之间肯定互相能到达)。用tarjan找出所有的连通分量,如果某个连通分量里有连到外面的边,则这个分量肯定不会是答案(分量图是有向的无环图,从分量1里连线到分量2中的边,分量2肯定没有变连回分量1,也就是1到达了2但是2不能到达1)。如果没有向外连边的连通分量不是1个就没有答案。
Popular Cows
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 |
[Discuss]
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxV=11000,maxE=55000;
struct Edge
{
int to,next;
}edge[maxE];
int Adj[maxV],Size;
void init()
{
Size=0;
memset(Adj,-1,sizeof(Adj));
}
void Add_Edge(int u,int v)
{
edge[Size].to=v;
edge[Size].next=Adj[u];
Adj[u]=Size++;
}
int Low[maxV],DFN[maxV],Stack[maxV],Belong[maxV],num[maxV];
int Index,top,scc,n;
bool Instack[maxV];
void tarjan(int u)
{
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
for(int i=Adj[u];~i;i=edge[i].next)
{
v=edge[i].to;
if(!DFN[v])
{
tarjan(v);
Low[u]=min(Low[u],Low[v]);
}
else if(Instack[v])
{
Low[u]=min(Low[u],DFN[v]);
}
}
if(Low[u]==DFN[u])
{
scc++;
do
{
v=Stack[--top];
Instack[v]=false;
num[scc]++;
Belong[v]=scc;
}while(v!=u);
}
}
int solve(int n)
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
Index=scc=top=0;
for(int i=1;i<=n;i++)
{
if(!DFN[i]) tarjan(i);
}
return scc;
}
bool yes[maxV];
int main()
{
int m;
while(scanf("%d%d",&n,&m)!=EOF&&n)
{
init();
memset(yes,true,sizeof(yes));
int a,b;
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
Add_Edge(a,b);
}
int scc=solve(n);
for(int i=1;i<=n;i++)
{
for(int j=Adj[i];~j;j=edge[j].next)
{
int v=edge[j].to,u=i;
if(Belong[v]!=Belong[u])
{
yes[Belong[u]]=false;
}
}
}
int ans=0,tot=0;
for(int i=1;i<=scc;i++)
{
if(yes[i])
{
tot++;
ans+=num[i];
}
}
if(tot!=1) ans=0;
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- POJ-2186 Popular Cows (强连通缩点)
- poj 2186——Popular Cows
- poj 2186 Popular Cows(Kosaraju + 变形)
- POJ 2186:Popular Cows(tarjan算法入门题)
- POJ 2186 Popular Cows
- poj 2186 Popular Cows (tarjan + 缩点)
- poj 2186 Popular Cows
- POJ 2186-Popular Cows
- poj 2186 Popular Cows 缩点
- POJ 2186 Popular Cows
- poj 2186 Popular Cows
- POJ 2186 Popular Cows【强连通Kosaraju+缩点】
- POJ 2186 Popular Cows
- POJ 2186 Popular Cows(强联通分量)
- POJ - 2186 - Popular Cows (tarjan)
- POj 2186 Popular Cows[连通分量]
- POJ 2186 Popular Cows(korasaju Algorithm求强连通分量)
- POJ 2186 Popular Cows 强连通分量 Kosaraju算法
- POJ_2186_Popular Cows_强连通分量
- poj 2186 Popular Cows