【codevs 2604】舞会邀请

来源:互联网 发布:数据的统计 编辑:程序博客网 时间:2024/06/05 07:12

题目描述 Description

Smart是一位颇有成就的艺术家,他因油画作品《我爱北京天安门》闻名于世界。现在,他为了报答帮助他的同行们,准备开一个舞会。
Smart准备邀请n个已经确定的人,可是问题来了:
这n个人每一个人都有一个小花名册,名册里面写着他能够通知到的人的名字。比如说在A的人名单里写了B,那么表示A能够通知到B;但是B的名单里不见得有A,也就是说B不见得能够通知到A。
Smart觉得需要确定自己需要通知到多少个人(人数m),能够实际将所有n个人都通知到。并求出一种方案以确定m的最小值是多少。
注意:自己的名单里面不会有自己的名字。

输入描述 Input Description
第一行一个数n(1≤n≤200)。接下来n行,第i+1行表示编号为i的人的小花名册名单,名单以0结束。

输出描述 Output Description
一个整数,即m的值。

样例输入 Sample Input
5 1

2 0

1 3 0

0

0

1 0

样例输出 Sample Output
2

数据范围及提示 Data Size & Hint
1≤n≤200

Tarjan缩点后求入度为0的环/点的数量。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>using namespace std;const int maxn=10000+10;int first[maxn],nxt[maxn],tot=0;int dfn[maxn],low[maxn],scc[maxn],size[maxn],ru[maxn];int dfs_clock,scc_num;int n;stack<int>q;struct edge{    int f,t;}l[maxn];void build(int f,int t){    l[++tot]=(edge){f,t};    nxt[tot]=first[f];    first[f]=tot;}void dfs(int u){    low[u]=dfn[u]=++dfs_clock;    q.push(u);    for(int i=first[u];i;i=nxt[i])    {        int w=l[i].t;        if(!dfn[w])        {            dfs(w);            low[u]=min(low[u],low[w]);        }        else if(!scc[w])        {            low[u]=min(low[u],dfn[w]);        }    }    if(low[u]==dfn[u])    {        scc_num++;        while(!q.empty())        {            int x=q.top();            q.pop();            scc[x]=scc_num;            size[scc_num]++;            if(x==u) break;        }    }    return;}int main(){    int t,ans=0;    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        while(~scanf("%d",&t)&&t)        build(i,t);    }    for(int i=1;i<=n;i++)    {        if(!dfn[i]) dfs(i);    }    for(int i=1;i<=n;i++)    {        for(int j=first[i];j;j=nxt[j])        {            int w=l[j].t;            if(scc[i]!=scc[w]) ru[scc[w]]++;        }    }    for(int i=1;i<=scc_num;i++)    {        if(!ru[i]) ans++;    }    printf("%d\n",ans);    return 0;}

大爷还有一个利用传递闭包的暴力做法%%%
不过复杂度n^3 数据再强一点的话就不好过了QWQ

原创粉丝点击