标签:
Description
Input
Output
Sample Input
5 2 4 3 0 4 5 0 0 0 1 0
Sample Output
1 2
今天模拟赛的第一题
题意是给一个图,第一问求最少选多少个点,使得从这些点出发能遍历整张图。第二问是最少添加多少有向边,使得整个图变成强连通图
第一问比较sb。tarjan缩点完入度为0的点的个数
第二问有点坑……令G{E,V}表示某一弱连通图,I(G)表示G中入度为0的点的个数,O(G)表示G中出度为0的点的个数。
原来我以为是Σmax(I(i),O(i))。其实是max(ΣI(i),ΣO(i))。这区别很容易看出来吧
#include<cstdio>
#include<iostream>
#define LL long long
using namespace std;
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
struct edge{int to,next;}e[1000010];
int n,cnt,cnt3,tt,sumi,sumo;
int head[100010];
bool inset[100010];
int dfn[100010],low[100010];
int zhan[100010],top;
int belong[100010];
int I[100010],O[100010];
inline void ins(int u,int v)
{
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
inline void dfs(int x)
{
zhan[++top]=x;inset[x]=1;
dfn[x]=low[x]=++tt;
for (int i=head[x];i;i=e[i].next)
{
if (!dfn[e[i].to])
{
dfs(e[i].to);
low[x]=min(low[x],low[e[i].to]);
}else if (inset[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
}
if (low[x]==dfn[x])
{
cnt3++;
int p=-1;
while (p!=x)
{
p=zhan[top--];
belong[p]=cnt3;
inset[p]=0;
}
}
}
inline void tarjan()
{for (int i=1;i<=n;i++)if (!dfn[i]) dfs(i);}
int main()
{
n=read();
for (int i=1;i<=n;i++)
{
int x;
while (scanf("%d",&x)&&x)ins(i,x);
}
tarjan();
for (int i=1;i<=n;i++)
{
for (int j=head[i];j;j=e[j].next)
if (belong[i]!=belong[e[j].to])
{
O[belong[i]]++;
I[belong[e[j].to]]++;
}
}
if (cnt3==1)
{
printf("1\n0\n");
return 0;
}
for (int i=1;i<=cnt3;i++)
{
if (!I[i])sumi++;
if (!O[i])sumo++;
}
printf("%d\n%d\n",sumi,max(sumi,sumo));
return 0;
}
标签:
原文地址:http://www.cnblogs.com/zhber/p/4175862.html