poj 1236 Network of Schools 1 (tarjan 缩点)

来源:互联网 发布:数据比对公式vlookup 编辑:程序博客网 时间:2024/06/03 02:27

poj 1236 Network of Schools 1

给定一个有向图,求:

1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点。

2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点。

先处理环的问题,tarjan 缩点

对于第一个问题就是求DAG上入度为0的点个数。

对于第一个问题就是求DAG上max(入度为0的点数,出度为0的点数,入出点相连);

注:n=1时单独考虑

#include<cstdio>#include<algorithm>#include<cstring>#include<map>#include<string>#include<stack>using namespace std;stack <int> state;map <string,int> id;const int N = 10010;struct Edge{    int to, next, from, del;}ed[N*2];int head[N], place[N], vis[N], exi[N], nodel[N];int dfn[N], low[N];int duin[N], duout[N];int idc, cnt, idx, tot, ans, n;void adde(int u,int v){    ed[++idc].to = v;    ed[idc].from = u;    ed[idc].next = head[u];    head[u] = idc;}void tarjan(int u){    dfn[u] = low[u] = ++idx;    vis[u] = exi[u] = 1;    state.push(u);    for(int k=head[u]; k; k=ed[k].next){        int v = ed[k].to;        if( !vis[v] ){            tarjan( v );            low[u] = min(low[u], low[v]);        }        else if( exi[v] ){            low[u] = min(low[u], dfn[v]);        }    }    if(dfn[u] == low[u]){        int t = -1;        while(t != u){            t = state.top();            place[t] = u;//强连通分量缩点到u            exi[t] = 0;            state.pop();        }        place[u] = u;    }}void cut(){    for(int i=1; i<=idc; i++){        int u = ed[i].from, v = ed[i].to;        if(place[u] == u && place[v] == v) {            duin[v]++; duout[u]++; //统计入度出度            continue;        }        if(place[u] != place[v]) adde(place[u], place[v]);         ed[i].del = 1;//删边        if(place[u] != u) nodel[u] = 1;//删点        if(place[v] != v) nodel[v] = 1;    }}void dfs(int u){    for(int k=head[u]; k; k=ed[k].next){        int v = ed[k].to;        if( ed[k].del ) continue;        if( !vis[v] ){            dfs(v);            vis[v] = 1;        }    }}void work1(){    for(int i=1; i<=n; i++){        if( !duin[i] && !nodel[i] ) tot++;    }}void work2(){    int ans1 = 0, ans2 = 0, mm = 0;    for(int i=1; i<=n; i++){        if( nodel[i] ) continue;        if( !duin[i] ) ans1++;        if( !duout[i] ) ans2++;        mm++;    }    ans = max(ans1, ans2);    if( mm == 1 ) ans = 0;//只有一个点的情况}int main(){    //freopen("break.in", "r", stdin);     //freopen("break.out", "w", stdout);    scanf("%d", &n); int cc;    for(int i=1; i<=n; i++){        scanf("%d", &cc);        while( cc ){            adde(i, cc);            scanf("%d", &cc);        }    }    for(int i=1; i<=n; i++)        if(!vis[i]) tarjan(i);    cut();    work1();    work2();    printf("%d\n%d", tot, ans);    return 0;}
阅读全文
0 0
原创粉丝点击