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