情报网络

Description

看过一些间谍故事的人都知道,谍报机关是一个庞大的网络,间谍与间谍之间接头不一定要碰面的,所以存在a能给b传递情报而b去无法联络到a的情况,所有的接头线路组成一个网络,也就是间谍网络。
现在在米国首都,P.R.C的英勇无敌的谍报人员已经建立起了一个庞大的间谍网络,这个谍报网络的负责人就是神秘的J.T.R,他负责将国内得到的命令传达给谍报网络中的成员,并由他们继续传递下去,当然命令要保证谍报网络中的所有间谍都会被传达到。
可是随着谍报网的扩大,J.T.R可能不得不与多名成员接头,来保证网络中的所有成员都被通知到。这无疑增大了他的危险性,所以他想增加一些接头的线路,使得他只需要与一名成员接头,就可以将情况传达给所有的成员。当然增加越多接头线路,就会使整个间谍网络暴露的机会越大,所以他想增加尽量少的接头线路来满足他的要求。当然,如果一直同一名间谍接头也会增大暴露的危险,所以他又添加了一个小小的要求,那就是不管他与谁接头,都可以将情况传递给所有的人。

Input

包括m+1行。
第一行两个数n、m,表示一共有n个成员,有m条接头线路。
下接m行,每行包含2个数字a、b,表示a可以通知到b。
保证输入的图是连通的。
n<=5000 m<=20000

Output

包括1行,为一个数s,表示最少增加的接头线路的条数。

Sample Input

3 2
1 2
1 3

Sample Output

2
//只要添加2到1 与 3到1的接头路线,就可以满足要求了。


题解:与Pku1236 Network of Schools 第二个问题意思一样,代码只需要删掉Pku1236 Network of Schools的第一问就好了,详情请参考我的题解:
Pku1236 Network of Schools


下面附上代码:
#include
#include
using namespace std;
int n,k,ans,group,cnt,top,total,ans2,x,tot=0,m,y;
int belong[10010],du[10010],first[10010],dfn[10010],low[10010],st[10010],du2[10010];
struct node
{
    int s,e,next;
}v[50050];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void tarjan(int k)
{
    dfn[k]=++cnt;
    low[k]=cnt;
    st[++top]=k;
    int ttt=top;
    for(int i=first[k];i;i=v[i].next)
        if(!belong[v[i].e])
        {
            if(!dfn[v[i].e])tarjan(v[i].e);
            low[k]=min(low[k],low[v[i].e]);
        }
    if(dfn[k]==low[k])
    {
        total++;
        for(int i=ttt;i<=top;i++)
            belong[st[i]]=total;
        top=ttt-1;
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read();
        v[i].next=first[x];
        first[x]=i;
        v[i].s=x;v[i].e=y;
    }
    for(int i=1;i<=n;i++)
        if(!belong[i])tarjan(i);
    for(int i=1;i<=m;i++)
        if(belong[v[i].s]!=belong[v[i].e]) {++du[belong[v[i].s]];++du2[belong[v[i].e]];}
    for(int i=1;i<=total;i++)
    {
        if(du2[i]==0)ans++;
        if(du[i]==0)ans2++;
    }
    ans2=max(ans,ans2);
    if(total==1)ans2=0;
    printf("%d",ans2);
    return 0;
}
//求ans的过程与本题无关,只需要看关于ans2的就好了(本人太懒,懒得去删了)。

你可能感兴趣的:(----tarjan)