先附上大佬博客Orz:https://blog.csdn.net/lianai911/article/details/43446089
这道题题都没读懂。。看了大佬博客才明白要干什么emmmmm...问题如下:
1、最少向几台电脑投放文件,就能使所有电脑都接收到文件。
2、最少向这n台电脑构成的图中添加几条边,就能使只向一台电脑投放文件,所有电脑都能接收到。
问题1:一开始想的是求联通块的个数,但后来想了想发现不对:可能两个联通块之间有一条单向边相连,这样其实只需要向一台电脑投放文件就可以。所以最后问题应转化为:强连通分量“缩点”后,入度为0的点的个数。
问题2:这问一开始没什么思路QAQ...看了大佬博客后发现问题转化为:强连通分量“缩点”后,在入度为0的点和出度为0的点之间最少加多少边使之构成环。那这就是max(入度为0的点,出度为0的点)。
附上AC代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
#define ll long long
typedef pair<int,int>pp;
const double pi=acos(-1.0);
const double eps=1e-9;
const int INF=0x3f3f3f3f;
const ll MOD=1e9+7ll;
const int MAX=110;
int n;
struct Edge
{
int to,next;
}edge[MAX*MAX];
int head[MAX],tol;
int low[MAX],dfn[MAX],st[MAX],be[MAX];
int index,top;
int scc;//强连通分量的个数
bool vis[MAX];
int num[MAX];
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edge[tol].to=v;edge[tol].next=head[u];head[u]=tol++;
}
void tarjan(int u)
{
int v;
low[u]=dfn[u]=++index;
st[top++]=u;
vis[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
if(low[u]>low[v])
low[u]=low[v];
}
else if(vis[v]&&low[u]>dfn[v])
low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
scc++;
do
{
v=st[--top];
vis[v]=false;
be[v]=scc;
num[scc]++;
}while(v!=u);
}
}
void solve()
{
memset(dfn,0,sizeof(dfn));
memset(vis,false,sizeof(vis));
memset(num,0,sizeof(num));
index=scc=top=0;
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
}
int main()
{
while(scanf("%d",&n)==1)
{
init();
int x;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
while(x!=0)
{
addedge(i,x);
scanf("%d",&x);
}
}
solve();
if(scc==1)
{
printf("1\n0\n");
continue;
}
int in[MAX],out[MAX];
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for(int i=1;i<=n;i++)
for(int j=head[i];j!=-1;j=edge[j].next)
{
int k=edge[j].to;
if(be[i]!=be[k])
{
in[be[k]]++;
out[be[i]]++;
}
}
int nin=0,nout=0;
for(int i=1;i<=scc;i++)//注意循环从1到scc
{
if(in[i]==0)
nin++;
if(out[i]==0)
nout++;
}
int ans=max(nin,nout);
printf("%d\n%d\n",nin,ans);
}
return 0;
}