POJ 2168 Popular cows [Tarjan 缩点]
Popular Cows
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 39115 | Accepted: 15937 |
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
Hint
Cow 3 is the only cow of high popularity.
Tarjan入门题,果然有的算法入门题就需要应用啊。。
求强连通分量的板子差不多找到个舒服的了,为了速度起见还是不用STL了吧。
这个题,问有没有点能被其他所有的点到达。强连通分量中是各自满足条件的
由于有向无环图中,出度为零的点是满足这个条件的。所以我们可以使用tarjan来找到所有的强连通分量,并进行缩点,对强连通分量进行编号,把每个点标记一下所属于的强连通分量,然后把图遍历一下,求出每个强连通分量的出度。
最后判断出度为0的强连通分量个数,若为1个,则存在,输出编号为这个的点个数即可。否则不存在。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<vector> 8 #include<stack> 9 //#include<bits/stdc++.h> 10 using namespace std; 11 #define mem(a,b) memset(a,b,sizeof(a)) 12 #define ll long long 13 #define inf 1000000000 14 #define maxn 10005 15 #define maxm 100005 16 #define eps 1e-10 17 #define for0(i,n) for(int i=1;i<=(n);++i) 18 #define for1(i,n) for(int i=1;i<=(n);++i) 19 #define for2(i,x,y) for(int i=(x);i<=(y);++i) 20 #define for3(i,x,y) for(int i=(x);i>=(y);--i) 21 #define mod 1000000007 22 inline int read() 23 { 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9') {x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 struct node{ 30 int to,next; 31 }edge[maxm]; 32 int n,m,head[maxn],vis[maxn],dfn[maxn],low[maxn],du[maxn],num[maxn],cnt,timi,stack1[maxn],top,cut; 33 void init() 34 { 35 memset(dfn,0,sizeof(dfn)); 36 memset(low,0,sizeof(low)); 37 memset(head,-1,sizeof(head)); 38 memset(vis,0,sizeof(vis)); 39 memset(num,0,sizeof(num)); 40 memset(du,0,sizeof(du)); 41 cnt=0; 42 timi=1; 43 top=0; 44 cut=0; 45 } 46 stack <int> s; 47 void addedge(int u,int v) 48 { 49 edge[cnt].to=v; 50 edge[cnt].next=head[u]; 51 head[u]=cnt; 52 cnt++; 53 } 54 void tarjan(int u) 55 { 56 dfn[u]=timi; 57 low[u]=timi; 58 timi++; 59 s.push(u); 60 //stack1[top]=u;top++; 61 vis[u]=1; 62 for(int i=head[u];i!=-1;i=edge[i].next) 63 { 64 int v=edge[i].to; 65 if(!dfn[v]) { 66 tarjan(v); 67 low[u]=min(low[u],low[v]); 68 } 69 else{ 70 low[u]=min(low[u],dfn[v]); 71 } 72 } 73 if(low[u]==dfn[u]) 74 { 75 cut++; 76 int x=s.top(); 77 while(!s.empty()&&x!=u) 78 { 79 vis[s.top()]=0; 80 //vis[stack1[top]]=2; 81 num[s.top()]=cut; 82 s.pop(); 83 x=s.top(); 84 } 85 num[s.top()]=cut; 86 s.pop(); 87 } 88 } 89 int main() 90 { 91 int a,b; 92 while(~scanf("%d%d",&n,&m)) 93 { 94 init(); 95 for(int i=1;i<=m;++i) 96 {scanf("%d%d",&a,&b); 97 addedge(a,b); 98 } 99 for(int i=1;i<=n;++i) 100 { 101 if(!dfn[i]) tarjan(i); 102 } 103 for(int i=1;i<=n;++i) 104 { 105 for(int j=head[i];j!=-1;j=edge[j].next) 106 { 107 if(num[i]!=num[edge[j].to]) {du[num[i]]++; 108 } 109 } 110 } 111 int sum=0,x; 112 for(int i=1;i<=cut;++i) 113 { 114 if(!du[i]) {sum++;x=i;} 115 } 116 if(sum==1) 117 { 118 sum=0; 119 for(int i=1;i<=n;++i) 120 if(num[i]==x) sum++; 121 printf("%d\n",sum); 122 } 123 else puts("0\n"); 124 } 125 return 0; 126 }