|
这道题有两问
第一问很简单,先tarjin缩一下点,然后找出所有入度为0的点,那么这些点是必须要副本的,其他的点一定可以有这些点到达,所以答案就是所有入度为0的点
第二问,有一个小结论,就是一个有向图我们只需要最多连max(入度为0的点的个数,初度为0的点的个数)条边,那么个图就可以成为强连通的,即从任意一个点可以到达另外所有点,但当只有一个强连通分量的时候要输出0而不是1
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 inline int read(){ 5 int x=0;int f=1;char ch=getchar(); 6 while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} 7 while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();} 8 return x*f; 9 } 10 const int MAXN=1e4+10; 11 namespace zhangenming{ 12 struct node{ 13 int x,y,next; 14 }e[MAXN]; 15 int linkk[MAXN],len=0,n; 16 inline void insert(int xx,int yy){ 17 e[++len].y=yy;e[len].x=xx;e[len].next=linkk[xx];linkk[xx]=len; 18 } 19 void init(){ 20 n=read(); 21 for(int i=1;i<=n;i++){ 22 int xx=read(); 23 while(xx){ 24 insert(i,xx); 25 xx=read(); 26 } 27 } 28 } 29 int vis[MAXN],stark[MAXN],ine[MAXN],cntt[MAXN]={},tot=0,top=0,cnt[MAXN]={},dfn[MAXN]={},low[MAXN],dfs_clock=0; 30 inline void tarjin(int st){ 31 //cout<<st<<endl; 32 dfn[st]=low[st]=++dfs_clock;vis[st]=1; 33 stark[++top]=st; 34 for(int i=linkk[st];i;i=e[i].next){ 35 if(!dfn[e[i].y]){ 36 //cout<<e[i].y<<endl; 37 tarjin(e[i].y); 38 low[st]=min(low[st],low[e[i].y]); 39 } 40 else if(vis[e[i].y]) low[st]=min(low[st],dfn[e[i].y]); 41 } 42 if(low[st]==dfn[st]){ 43 tot++; 44 int k; 45 do{ 46 k=stark[top--]; 47 ine[k]=tot; 48 vis[k]=0; 49 }while(k!=st); 50 } 51 } 52 void solve(){ 53 memset(vis,0,sizeof(vis)); 54 for(int i=1;i<=n;i++){ 55 if(!ine[i]) tarjin(i); 56 } 57 for(int i=1;i<=len;i++){ 58 int xx=e[i].x;int yy=e[i].y; 59 if(ine[xx]==ine[yy]) continue; 60 cnt[ine[yy]]++; 61 cntt[ine[xx]]++; 62 } 63 int sum1=0;int sum2=0; 64 for(int i=1;i<=tot;i++){ 65 if(!cnt[i]) sum1++; 66 if(!cntt[i]) sum2++; 67 } 68 cout<<sum1<<endl; 69 if(tot!=1) cout<<max(sum1,sum2)<<endl; 70 else cout<<0<<endl; 71 } 72 } 73 int main(){ 74 using namespace zhangenming; 75 init(); 76 solve(); 77 return 0; 78 }
代码
时间: 2024-10-10 23:06:52