• Network of Schools POJ 1236


    首先应该求出来连通分量,进行缩点,然后求每个分量的入度和出度,入度等于0的很明显都需要分发一个文件,至于需要添加几条边可以成为一个强连通,就是出度和入度最大的那个,因为需要把出度和入度相连。
    #include <cstdio> #include <iostream> #include <cstring> #include <cstring> #include <algorithm> #include <stack> #include <vector> using namespace std; #define maxn 105 int head[maxn],cnt; struct edge { int v,next; }e[maxn*maxn]; int sta[maxn],instack[maxn],dfn[maxn];//sta数组模拟栈 instack数组表示是否在栈中 ; int top,index,low[maxn],belong[maxn],bnt; void add(int u, int v) { e[cnt].v=v; e[cnt].next=head[u]; head[u]=cnt++; } void tarjan(int k) { dfn[k]=low[k]=++index; instack[k]=1; sta[++top]=k; int j; for(j=head[k];j!=-1;j=e[j].next) { int v=e[j].v; if(!dfn[v]) { tarjan(v); low[k]=min(low[k],low[v]); } else if(instack[v]) { low[k]=min(low[k],dfn[v]); } } if(dfn[k]==low[k]) { ++bnt; do { j=sta[top--]; instack[j]=0; belong[j]=bnt; }while(k!=j); } } void Init(int n) { cnt=bnt=index=top=0; for(int i=1;i<=n;i++) { head[i]=-1; dfn[i]=0; } } int main() { int n; while(~scanf("%d",&n)) { int u,v; Init(n); for(int i=1;i<=n;i++) { while(scanf("%d",&v),v) { add(i,v); } } for(int i=1;i<=n;i++)// if(!(dfn[i])) tarjan(i); int r[maxn]={0},c[maxn]={0},rn=0,cn=0; for(int i=1;i<=n;i++) { for(int j=head[i];j!=-1;j=e[j].next) { u=belong[i],v=belong[e[j].v];//u是v的父亲,所以u的出度+1,v的入度+1 if(u!=v) { c[u]++; r[v]++; } } } for(int i=1;i<=bnt;i++) { if(r[i]==0) rn++; if(c[i]==0) cn++; } if(bnt==1) printf("1 0 "); else printf("%d %d ",rn,max(rn,cn)); } return 0; }
  • 相关阅读:
    mysql 安装失败 start service执行不下去
    C# 打开钱箱支持北洋、佳博、爱普生
    CF1093E Intersection of Permutations [分块 +bitset]
    CF895C Square Subsets [线性基]
    线性基学习笔记
    长链剖分学习笔记
    GSS 系列题解
    P3206 [HNOI2010]城市建设 [线段树分治+LCT维护动态MST]
    线段树分治学习笔记
    [CF662C Binary Table][状压+FWT]
  • 原文地址:https://www.cnblogs.com/mengzhong/p/4712491.html
Copyright © 2020-2023  润新知