现在的位置: 首页 > 综合 > 正文

nyoj 120 校园网络(强连通缩点+判断入度出度大小)

2018年01月14日 ⁄ 综合 ⁄ 共 3355字 ⁄ 字号 评论关闭
重在理解强连通,有的不是用强连通缩点写的,我觉得数据太弱,错误的程序都可以过,
注意定义变量是不能定义index,会编译错误,还有nodes[]结构体不能开的太小
描述

南阳理工学院共有M个系,分别编号1~M,其中各个系之间达成有一定的协议,如果某系有新软件可用时,该系将允许一些其它的系复制并使用该软件。但该允许关系是单向的,即:A系允许B系使用A的软件时,B未必一定允许A使用B的软件。

现在,请你写一个程序,根据各个系之间达成的协议情况,计算出最少需要添加多少个两系之间的这种允许关系,才能使任何一个系有软件使用的时候,其它所有系也都有软件可用。

输入
第一行输入一个整数T,表示测试数据的组数(T<10)
每组测试数据的第一行是一个整数M,表示共有M个系(2<=M<=100)。
随后的M行,每行都有一些整数,其中的第i行表示系i允许这几个系复制并使用系i的软件。每行结尾都是一个0,表示本行输入结束。如果某个系不允许其它任何系使用该系软件,则本行只有一个0.
输出
对于每组测试数据,输出最少需要添加的这种允许关系的个数。
样例输入
1
5
2 4 3 0
4 5 0
0
0
1 0
样例输出
2

模版代码:

 
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<stack>
using namespace std;

const int NV = 2005;
const int NE = 5005;

struct Tarjan {
    int dfn[NV];
    int low[NV];
    int index, scc, n;
    bool instack[NV];
    int root[NV];

    stack<int> S;
    struct Edge{
        int v , next, w;
        Edge () {}
        Edge (int V, int NEXT, int W) : v(V), next(NEXT), w(W){}
    }E[NE];
    int head[NV], size;

    inline void init (int nn) {
        n = nn, size = 0;
        memset(head, -1, sizeof(int) * (n + 1));
    }

    inline void insert (int u , int v, int w = 1) {
        E[size] = Edge(v, head[u], w);
        head[u] = size++;
    }

    void tarjan (int i) {
        dfn[i] = low[i] = ++index;
        instack[i] = true;
        S.push(i);
        for (int k = head[i]; k != -1; k = E[k].next) {
            int v = E[k].v;
            if (!dfn[v]) {
                tarjan(v);
                if(low[v] < low[i]) low[i] = low[v];
            } else if (instack[v] && dfn[v] < low[i])
                low[i] = dfn[v];
        }
        if (dfn[i] == low[i]) {
            scc++;
            int x;
            do{
                x = S.top();
                S.pop();
                instack[x] = false;
                root[x] = scc;
            }while (x != i);
        }
    }

    void Solve(){
        while (!S.empty()) S.pop();
        memset(dfn,0,sizeof(dfn));
        index = scc = 0;
        for (int i = 1; i <= n; i++) {
            if(!dfn[i]) tarjan(i);
        }
    }

    struct Relation {
        int u,v;
    }re[NE];
}G;

int main() {
    int n, m, in[NV], out[NV],i;
    int cas;
    scanf("%d",&cas);
    while(cas--) {
        scanf("%d", &n);
        G.init(n);
        int x,k=0;
        for(i=1;i<=n;i++)
        {
            while(scanf("%d",&x)&&x)
            {
                G.insert(i,x);
                G.re[k].u=i;
                G.re[k].v=x;
                k++;
            }
        }

        G.Solve();
        if (G.scc == 1)
        {
            puts("0");
            continue;
        }
        for (int i = 1; i <= G.scc; i++) {
            in[i] = out[i] = 0;
        }
        for (int i = 0; i <k; i++) {
            if (G.root[G.re[i].u] == G.root[G.re[i].v]) continue;
            in[ G.root[ G.re[i].v] ]++;
            out[ G.root[G.re[i].u] ]++;
        }
        int cnt_in = 0 , cnt_out = 0;
        for (int i = 1; i <= G.scc; i++ ) {
            if (in[i] == 0) cnt_in++;
            if (out[i] == 0) cnt_out++;
        }
        printf("%d\n", max(cnt_in,cnt_out));
    }
    return 0;
}
                

 

ac代码:

 
#include<cstdio>
#include<cstring>
#include<string>
#include<stack>
#include<algorithm>
using namespace std;
#define max(x,y) ((x)>(y)?(x):(y))

const int nv = 110;
const int ne = 5055;

int low[nv],dfn[nv],head[nv],root[nv],instack[nv];
int in[nv],out[nv];
int size,n,scc,inde;
stack<int>s;

struct edge
{
    int v,next;
}edges[ne];

struct node
{
    int u,v;
}nodes[ne];

void init()
{
    size=0;
    memset(head,-1,sizeof(head));
}
void insert(int x,int y)
{
    edges[size].v=y;
    edges[size].next=head[x];
    head[x]=size++;
}
void tarjan(int t)
{
    dfn[t]=low[t]=++inde;
    instack[t]=1;
    s.push(t);
    for(int j=head[t];j!=-1;j=edges[j].next)
    {
        int v=edges[j].v;
        if(!dfn[v])
        {
            tarjan(v);
            if(low[v]<low[t]) low[t]=low[v];
        }
        else if(instack[v]&&dfn[v]<low[t])
        {
            low[t]=dfn[v];
        }
    }
    if(dfn[t]==low[t])
    {
        scc++;
        int w;
        do
        {
            w=s.top();
            s.pop();
            instack[w]=0;
            root[w]=scc;
        }while(w!=t);
    }
}
void solve()
{
    while(!s.empty())
    s.pop();
    memset(dfn,0,sizeof(dfn));
    scc=0;inde=0;
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        tarjan(i);
    }
}
int main() {
    int i,cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&n);
        init();
        int x,k=0;
        for(i=1;i<=n;i++)
        {
            while(scanf("%d",&x)&&x)
            {
                insert(i,x);
                nodes[k].u=i;
                nodes[k].v=x;
                k++;
            }
        }
        solve();
        if (scc == 1)
        {
            puts("0");
            continue;
        }
        for (i = 1; i <= scc; i++) {
            in[i] = out[i] = 0;
        }
        for (i = 0; i <k; i++)
        {
            if (root[nodes[i].u] == root[nodes[i].v]) continue;
            in[root[nodes[i].v]]++;
            out[root[nodes[i].u]]++;
        }
        int indata = 0 , outdata = 0;
        for (i = 1; i <=scc; i++ )
        {
            if (in[i] == 0) indata++;
            if (out[i] == 0) outdata++;
        }
        printf("%d\n", max(indata,outdata));
    }
    return 0;
}
                

 

抱歉!评论已关闭.