POJ-1236(tarjan缩点)

来源:互联网 发布:天气预报哪个软件好 编辑:程序博客网 时间:2024/05/21 11:35

题目大意:给最少多少个学校发送软件才能通关网络使得全部学校得到该软件,然后最少加多少条边使得该图变成强连通图
题解思路:求入度为0的缩点个数就是个学校发送软件的个数
然后加边最优的方法肯定是从出度为0的点出发连到入度为0
如果入度为0的点大于出度为0的点那么就要入度为都接起来并且入度为0的至少有一条边
如果出度为0的点大于入度为0的点那就把出度和入度都连起来并且出度为0的至少有一条边连

题目链接

#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<stack>#include<algorithm>using namespace std;#define mes(s) memset(s,0,sizeof(s))const int mx = 110;vector<int>G[mx];stack<int>s;int dfn,cnt,sccno[mx],pre[mx],low[mx];int in_deg[mx],out_deg[mx];int n;void init(){    mes(sccno);    mes(pre);    mes(low);    mes(in_deg);    mes(out_deg);    dfn = cnt = 0;}void dfs(int u){    pre[u] = low[u] = ++dfn;    s.push(u);    for(int i = 0; i < G[u].size(); i++){        int v = G[u][i];        if(!pre[v]){            dfs(v);            low[u] = min(low[u],low[v]);        }        else if(!sccno[v]){            low[u] = min(low[u],low[v]);        }    }    if(pre[u] == low[u]){        ++cnt;        for(;;){            int x = s.top();            s.pop();            sccno[x] = cnt;            if(x == u)  break;        }    }}void solve(){    for(int i = 1; i <= n; i++)        if(!pre[i]) dfs(i);    if(cnt == 1){        cout<<1<<endl<<0<<endl;        return;    }    for(int i = 1; i <= n; i++)        for(int j = 0; j < G[i].size(); j++)            if(sccno[i] != sccno[G[i][j]])                in_deg[sccno[G[i][j]]]++,out_deg[sccno[i]]++;    int a = 0,b = 0;    for(int i = 1; i <= cnt; i++){        if(!in_deg[i])            a++;        else if(!out_deg[i])            b++;    }    cout<<a<<endl;    cout<<max(a,b)<<endl;}int main(){    while(~scanf("%d",&n)){        for(int i = 1; i <= n; i++){            int x;            G[i].clear();            while(scanf("%d",&x)&&x)                G[i].push_back(x);        }        init();        solve();    }    return 0;}