poj 2186 Popular Cows (tarjan + 缩点)
2012-08-25 16:29
423 查看
题意 :n头奶牛,m组关系(a b代表a认为b受欢迎)。求最后有多少头奶牛所有奶牛都认为它受欢迎。
思路:首先用tarjan算出连通分支数,将所有点都标上所属连通分支color。将每个分支看做一个点,若某点a受到另一点b联系,则说明该点a代表的连通分支中每个原始点都受到b中以及所有认为b受欢迎的点的欢迎,所以此处用dfs计算出每个分支中被多少人欢迎。
代码(比较繁琐):
测试数据:
思路:首先用tarjan算出连通分支数,将所有点都标上所属连通分支color。将每个分支看做一个点,若某点a受到另一点b联系,则说明该点a代表的连通分支中每个原始点都受到b中以及所有认为b受欢迎的点的欢迎,所以此处用dfs计算出每个分支中被多少人欢迎。
代码(比较繁琐):
#include<iostream> #include<string.h> #define size 10010 using namespace std; struct E { int v, next; }e[size*5],e1[size*5]; int head[size],in[size],stack[size] ,head1[size]; int dfn[size], low[size]; int num[size] ,rd[size], lian[size]; int top ,top1 , s ,color , step ,sum; int n,m; void init() { for(int i=0;i<size;i++) { head[i]=head1[i]=-1; in[i]=stack[i]=dfn[i]=low[i]=num[i]=lian[i]=0; } step=top=top1=color=0; s=-1; } void insert(int u , int v) { e[top].v=v; e[top].next=head[u]; head[u]=top++; } void insert1(int u , int v) { e1[top1].v=v; e1[top1].next=head1[u]; head1[u]=top1++; } void tarjan(int u) { int v; dfn[u]=low[u]=++step; in[u]=1; stack[++s]=u; for(int i=head[u];i!=-1;i=e[i].next) { v=e[i].v; if(!dfn[v]) { tarjan(v); if(low[v]<low[u]) low[u]=low[v]; } else if(in[v] && dfn[v]<low[u]) low[u]=dfn[v]; } if(dfn[u]==low[u]) { color++; int c=0; // cout<<endl<<"color "<<color<<" : "<<endl; do { v=stack[s--]; in[v]=0; lian[v]=color; //cout<<v<<" "; c++; }while(u!=v); num[color]=c; } } void dfs(int u)//连通分支u受到(xn-->...-->x1-->v-->u)所有v以及xi分支中所有原始点的欢迎。 { for(int i=head1[u];i!=-1;i=e1[i].next) { int v=e1[i].v; if( !low[ v]) { // cout<<u<<"-------"<<v<<endl; low[v]=1; dfs(v); sum+=num[v]; } } } int countRd() { int max=0 , t=0; //cout<<"color= "<<color<<endl; for(int i=1;i<=n;i++) { for(int j=head[i]; j!=-1; j=e[j].next) { int v=e[j].v; // cout<<i<<"************"<<v<<endl; if(lian[i]!=lian[v]) { insert1(lian[v],lian[i]); //用e1记录每个连通分支间的关系。 } } } for(int i=1;i<=color;i++) { rd[i]=0; //cout<<"rd["<<i<<"]=****= "<<rd[i]<<endl; sum=rd[i]; for(int j=1;j<=color;j++) low[j]=0; dfs(i); rd[i]=sum+num[i] ; // cout<<"rd["<<i<<"]= "<<rd[i]<<endl; } for(int i=1;i<=color;i++) { if(rd[i]==n) t+=num[i]; } return t; } int main() { int a, b; while(scanf("%d%d",&n,&m)!=EOF) { init(); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); if(a!=b) insert(a, b); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); // cout<<"n= "<<n<<endl; printf("%d\n",countRd()); } return 0; }
测试数据:
input 3 3 1 2 2 3 3 1 3 3 1 2 2 1 2 3 5 4 1 4 2 4 3 4 5 4 5 5 1 2 2 3 3 1 1 4 4 5 5 6 1 2 2 3 3 1 1 4 4 5 5 3 2 2 1 2 2 1 3 2 1 2 2 1 6 6 1 2 2 3 3 1 1 4 4 5 5 3 5 6 1 2 2 3 3 1 1 4 4 5 5 4 5 7 4 1 1 2 2 3 3 1 1 4 4 5 5 4 5 6 1 2 2 3 3 1 1 4 4 5 5 1 7 9 1 2 2 3 3 1 4 5 5 6 6 4 4 7 7 1 1 7 6 6 1 2 2 3 3 1 4 5 5 6 6 4 4 4 1 2 2 3 3 1 1 4 4 4 1 2 2 3 3 1 4 1 5 6 1 2 2 3 3 1 5 1 5 4 3 4 7 9 1 2 2 3 3 1 5 1 5 4 3 4 4 7 7 6 6 4 output 3 1 1 1 5 2 0 0 2 5 5 4 0 1 3 1 3
相关文章推荐
- POJ 2186 popular cows (tarjan + 缩点)
- poj 2186 Popular Cows (tarjan缩点)
- POJ 2186 Popular Cows (Tarjan + 缩点)
- POJ_2186 Popular Cows (Tarjan 强连通分量 缩点)
- poj 2186 Popular Cows(Tarjan,强连通分量缩点)
- POJ 2186 Popular Cows【Tarjan缩点+建缩点图】
- POJ-2186 Popular Cows,tarjan缩点找出度为0的点。
- POJ 2186 -- Popular Cows【强连通分支 && Tarjan缩点】
- poj 2186 Popular Cows【tarjan求scc个数&&缩点】【求一个图中可以到达其余所有任意点的点的个数】
- POJ 2186 Popular Cows 【Tarjan+缩点】
- poj 2186 Popular Cows(tarjan + 强连通分量 + 缩点)
- POJ 2186 Popular Cows -- tarjan 缩点
- POJ 2186 Popular Cows(tarjan缩点)
- (tarjan缩点)poj 2186 Popular Cows
- poj 2186 Popular Cows(Tarjan)
- POJ 2186 Tarjan 缩点 解题报告
- POJ - 2186 - Popular Cows (tarjan)
- POJ 2186 Popular Cows(强连通分量缩点,Tarjan算法)
- POJ 2186 Popular Cows (缩点)
- poj 2186: Popular Cows(tarjan基础题)