POJ 2186 Popular Cows

来源:互联网 发布:如来神掌裹裹抢单软件 编辑:程序博客网 时间:2024/05/03 07:35

【题意】给定牛群有n头,有m条关系表示x认为y受欢迎,若x认为y受欢迎,y认为z受欢迎,则x认为z受欢迎,问几头牛被其他所有牛欢迎?


【分析】分类讨论欢迎的情况:(1)组成环 (2)不成环
对于(1),又由“若x认为y受欢迎,y认为z受欢迎,则x认为z受欢迎”,易想到用强联通分量化成无向DAG
对于(2),再搜一遍,根据定理,若出边为0则输出
注:tarjan算法79ms,Kosaraju算法119ms,tarjan还是快一些的

【代码】
(1)KOSARAJU算法
#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;const int N=10070;const int M=64020;struct G{int v,next;};G map[M];int n,m,dfn[N],low[N],tot,d[N],hd[N],s[N],c[N],v[N],color;void ins(int u,int v){map[++tot].v=v;map[tot].next=hd[u];hd[u]=tot;}void init(void){scanf("%d%d",&n,&m);while (m--){int x,y;scanf("%d%d",&x,&y);ins(x,y);}}int min(int i,int j){return i<j?i:j;}void tarjan(int u){dfn[u]=low[u]=++tot;s[++s[0]]=u;int t=hd[u];while (t){if (!dfn[map[t].v]){tarjan(map[t].v);low[u]=min(low[u],low[map[t].v]);}else if (!c[map[t].v]) low[u]=min(low[u],dfn[map[t].v]);t=map[t].next;}if (low[u]==dfn[u]){color++;while (s[0]&&s[s[0]]^u) c[s[s[0]--]]=color;if (s[0]) c[s[s[0]--]]=color;}}void GCC(int u){v[u]++;int t=hd[u];while (t){if (!v[map[t].v]) GCC(map[t].v);d[c[u]]+=c[u]!=c[map[t].v];t=map[t].next;}}void work(void){tot=0;for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);for (int i=1;i<=n;i++) if (!v[i]) GCC(i);int t=-1,cnt=0;for (int i=1;i<=color;i++) if (!d[i]) t=(t==-1?i:0);for (int i=1;i<=n;i++) cnt+=t==c[i];printf("%d\n",cnt);}int main(void){init();work();return 0;}

(2)tarjan算法
#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;const int N=10070;const int M=64020;struct G{int v,next;};G map[M];int n,m,dfn[N],low[N],tot,d[N],hd[N],s[N],c[N],v[N],color;void ins(int u,int v){map[++tot].v=v;map[tot].next=hd[u];hd[u]=tot;}void init(void){scanf("%d%d",&n,&m);while (m--){int x,y;scanf("%d%d",&x,&y);ins(x,y);}}int min(int i,int j){return i<j?i:j;}void tarjan(int u){dfn[u]=low[u]=++tot;s[++s[0]]=u;int t=hd[u];while (t){if (!dfn[map[t].v]){tarjan(map[t].v);low[u]=min(low[u],low[map[t].v]);}else if (!c[map[t].v]) low[u]=min(low[u],dfn[map[t].v]);t=map[t].next;}if (low[u]==dfn[u]){color++;while (s[0]&&s[s[0]]^u) c[s[s[0]--]]=color;if (s[0]) c[s[s[0]--]]=color;}}void GCC(int u){v[u]++;int t=hd[u];while (t){if (!v[map[t].v]) GCC(map[t].v);d[c[u]]+=c[u]!=c[map[t].v];t=map[t].next;}}void work(void){tot=0;for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);for (int i=1;i<=n;i++) if (!v[i]) GCC(i);int t=-1,cnt=0;for (int i=1;i<=color;i++) if (!d[i]) t=(t==-1?i:0);for (int i=1;i<=n;i++) cnt+=t==c[i];printf("%d\n",cnt);}int main(void){init();work();return 0;}

【小结】一种转化思想,有向图转化为无向图,从而多了某些性质

                                             
0 0
原创粉丝点击