您的位置:首页 > 运维架构

POJ 2186 Popular Cows

2014-11-27 13:10 218 查看

【题意】给定牛群有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
,low
,tot,d
,hd
,s
,c
,v
,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
,low
,tot,d
,hd
,s
,c
,v
,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;
}


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


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: