Description
我们的郭嘉大大在曹操这过得逍遥自在,但是有一天曹操给了他一个任务,在建邺城内有N(<=1000)个袁绍的奸细,将他们从1到N进行编号,同时他们之间存在一种传递关系,即若C[i,j]=1,则奸细i能将消息直接传递给奸细j。
现在曹操要发布一个假消息,需要传达给所有奸细,而我们的郭嘉大大则需要传递给尽量少的奸细使所有的奸细都知道这一个消息,问我们至少要传给几个奸细
Input
文件的第一行为N,第二行至第N+1行为N*N的矩阵(若第I行第J列为1,则奸细I能将消息直接传递给奸细J,若第I行第J列为0,则奸细I不能将消息直接传递给奸细J)。
Output
输出文件只有一行:即我们的郭嘉大大首先至少要传递的奸细个数。
Sample Input
8
0 0 1 0 0 0 0 0
1 0 0 1 0 0 0 0
0 1 0 1 1 0 0 0
0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 1
0 0 0 0 0 0 1 0
Sample Output
2
思路
- tarjan求强连通分量版题
- 求强连通分量
代码
#include <iostream>
#include <cstdio>
#define maxn 1005
using namespace std;
int head[maxn],cnt,r[maxn],ans;
int num,dfn[maxn],low[maxn],visit[maxn],stack[maxn],index,belong[maxn];
struct fdfdfd{int next,to;}e[500005];
void addedge(int x,int y){e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;}
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
visit[x]=1; stack[++index]=x;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]);
else if(visit[v]) low[x]=min(low[x],dfn[v]);
}
if(low[x]==dfn[x])
{
++num;
do{
belong[stack[index]]=num;
visit[stack[index--]]=0;
}while(x!=stack[index+1]);
}
}
int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1,temp;j<=n;++j)
{
scanf("%d",&temp);
if(temp) addedge(i,j);
}
cnt=0;
for(int i=1;i<=n;++i)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;++i)
for(int j=head[i];j;j=e[j].next)
{
int v=e[j].to;
if(belong[i]!=belong[v]) ++r[belong[v]];
}
for(int i=1;i<=num;++i)
if(!r[i]) ++ans;
printf("%d
",ans);
return 0;
}