题意:电脑可以向自己list的电脑传输文件,而且是秒传(我们学校的网络能这么好,就帅死了),一、问最少向几个电脑投文件,二、连接最少的边使图成为强连通图
解法:缩点,一个强连通分量为一个点(抽象的),因为一个连通分量内文件是可以互传的,相当于一个点(是不是很像并查集),扫描所有的边,统计各个分量间的出度入度关系。
问题一:入度为零的分量个数
问题二:max(入度为零的个数,出度为零的个数),道理应该挺简单的吧。
/*
----------------------------------
Love is more than a word.
It says so much.
When I see these four letters,
I almost feel your touch.
This is only happened since
I fell in love with you.
Why this word does this,
I haven't got a clue.
To My Goddess
CY
----------------------------------
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<deque>
#include<map>
#include <stdio.h>
#include <queue>
#define maxn 10000+5
#define maxm 155
#define ull unsigned long long
#define ll long long
#define reP(i,n) for(i=1;i<=n;i++)
#define REP(i,a,b) for(i=a;i<=b;i++)
#define rep(i,n) for(i=0;i<n;i++)
#define cle(a) memset(a,0,sizeof(a))
#define clehead(a) rep(i,maxn)a[i]=-1
/*
The time of story :
** while(1)
{
once upon a time,
there was a mountain,
on top of which there was a temple,
in which there was an old monk and a little monk.
Old monk was telling stories inside the temple.
What was he talking about?
** }
ÎûÎû
(*^__^*)
*/
#define sci(a) scanf("%d",&a)
#define scd(a) scanf("%lf",&a)
#define pri(a) printf("%d",a)
#define prie(a) printf("%d\n",a)
#define prd(a) printf("%lf",a)
#define prde(a) printf("%lf\n",a)
#define pre printf("\n")
#define LL(x) x<<1
#define RR(x) x<<|1
#define pb push_back
#define mod 90001
#define PI 3.141592657
const ull INF = 1LL << 61;
const int inf = int(1e5)+10;
const double eps=1e-5;
using namespace std;
struct node
{
int v;
int next;
}edge1[maxn],edge2[maxn];
int head1[maxn],head2[maxn];
int used1[maxn],used2[maxn];
int Scc[maxn];//记录每个点所属的集合
int num[maxn];//记录第一次搜索的遍历顺序
int cnt1,cnt2;
int n;
int sig;
struct EDGE{//储存边的信息
int x,y;
}val[maxn];
void init()
{
cnt1=cnt2=1;
for(int i=1;i<=n;i++)head1[i]=head2[i]=-1;
cle(used1);
cle(used2);
cle(num);
}
void add(int x,int y)
{
edge1[cnt1].v=y,edge1[cnt1].next=head1[x],head1[x]=cnt1++;
edge2[cnt2].v=x,edge2[cnt2].next=head2[y],head2[y]=cnt2++;
}
void dfs1(int x,int &sig)
{
used1[x]=1;
for(int i=head1[x];i!=-1;i=edge1[i].next){
if(used1[edge1[i].v]==0)dfs1(edge1[i].v,sig);
}
num[sig++]=x;
}
void dfs2(int x,int sig)
{
used2[x]=1;
Scc[x]=sig;
for(int i=head2[x];i!=-1;i=edge2[i].next)
{
if(used2[edge2[i].v]==0)
{
dfs2(edge2[i].v,sig);
}
}
}
int main()
{
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(cin>>n)
{
init();
int i;int ip=1;
reP(i,n)
{
int temp;
while(cin>>temp&&temp)
{
val[ip].x=i,val[ip++].y=temp;
add(i,temp);
}
}
sig=1;
reP(i,n){
if(used1[i]==0)
{
dfs1(i,sig);
}
}
sig=1;
for(i=n;i>0;i--)
{
if(used2[num[i]]==0)
{
dfs2(num[i],sig++);
}
}
int in[maxn];
int out[maxn];
cle(in);
cle(out);
for(i=1;i<ip;i++)
{
if(Scc[val[i].x]!=Scc[val[i].y])
{
out[Scc[val[i].x]]++;
in[Scc[val[i].y]]++;
}
}
int ans1=0;
int ans2=0;
for(i=1;i<sig;i++)
{
if(in[i]==0)ans1++;
if(out[i]==0)ans2++;
}
//cout<<sig<<endl;
if(sig==2)
{
cout<<1<<endl;
cout<<0<<endl;
}
else
{
cout<<ans1<<endl;
cout<<max(ans1,ans2)<<endl;
}
}
return 0;
}