Pku1236 Network of Schools
n个学校构成一个有向图,通过m条边连接,一:问至少向图中多少个学校投放软件,可以使得所有学校直接或者间接的通过边(假设存在边(u,v),则向u投放v可以得到,而向v投放u不能通过v直接得到)得到软件(假设每次投放的软件无穷多)。二:问至少添加多少条有向边,可以使得只用向任意一个学校投放软件后,别的学校都能得到软件
输入
第一行给出数字N,N<=100
接下来N行给出每个点的连通情况,每行给出一些数字代表第i个学校与哪些学校相连接,每行输入以0代表结束
输出
如题
Sample Input
5
2 4 3 0
4 5 0
0
0
1 0
Sample Output
1
2
其实就是强连通缩点,
问一是统计缩点后有多少分量入度为0,
问二是指至少添加多少边使得图强连通。
然后统计入度为0的点的个数in和出度为0的点的个数ou,
则问一输出in,问二如果整个图强连通则输出0,否则输出max{in,ou}。
为什么是max{in,ou}?
因为要使得图强连通,则必定每个点的出度以及入度都不为0
#include<algorithm>
#include<cstdio>
using namespace std;
int son[10100],n,m,ans1,group,low[10100],dfn[10100],st[10100],tot,now[10100],used[11000],popp[11000],topp[11000],a[11000],b[11000],ans2;
void add(int x,int y)
{
tot++;
now[tot]=son[x];
son[x]=tot;
}
int top,sum,cnt,totle;
void dfs(int deep)
{
st[++top]=deep;
dfn[deep]=++cnt;
low[deep]=dfn[deep];
int nnow=top;
for(int i=son[deep];i;i=now[i])
if(!used[b[i]])
{
if(!dfn[b[i]])
dfs(b[i]);
low[deep]=min(low[b[i]],low[deep]);
}
if(dfn[deep]==low[deep])
{
totle++;
for(int i=nnow;i<=top;i++)
used[st[i]]=totle;
top=nnow-1;
}
}
int main()
{
int v,k=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&v);
while(v)
{
add(i,v);
a[++k]=i;
b[k]=v;
scanf("%d",&v);
}
}
for(int i=1;i<=n;i++)
if(!used[i])dfs(i);
for(int i=1;i<=k;i++)
if(used[a[i]]!=used[b[i]])
++popp[used[a[i]]],
topp[used[b[i]]]++;
for(int i=1;i<=totle;i++)
{
if(topp[i]==0)
ans1++;
if(popp[i]==0)
ans2++;
}
ans2=max(ans1,ans2);
if(totle==1)
ans2=0;
printf("%d\n%d",ans1,ans2);
}
#include<cstdio>
#include<algorithm>
using namespace std;
int s[10010],st[110],hea[110],en[110],in[110],dfn[110],low[110],cd[110],rd[110],num,cnt,top,n,m;
void tarjan(int x)
{
low[x]=dfn[x]=++num;
st[++top]=x;
for(int i=hea[x];i<en[x];i++)
{
int y=s[i];
if(!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(!in[y])
low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x])
{
cnt++;
while(top&&st[top]!=x)in[st[top--]]=cnt;
in[st[top--]]=cnt;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
en[i]=hea[i]=en[i-1];
while(scanf("%d",s+en[i])&&s[en[i]])en[i]++;
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
for(int j=hea[i];j<en[i];j++)
if(in[i]!=in[s[j]])
cd[in[i]]++,rd[in[s[j]]]++;
int c=0,r=0;
for(int i=1;i<=cnt;i++)
{
if(!cd[i])c++;
if(!rd[i])r++;
}
printf("%d\n",r);
if(cnt==1)puts("0");
else printf("%d\n",max(c,r));
return 0;
}

浙公网安备 33010602011771号