POJ 1523 无向图求割点

来源:互联网 发布:计步器软件哪个好用 编辑:程序博客网 时间:2024/06/09 17:52

无向图求割点的问题,仍然是用到Tarjan算法进行深搜,深搜过程中不断更新每个节点的dfn值和low值,对一个父亲节点u和其子节点v,每次搜索完其一个子节点,更新其low值,即节点u能通过一条其后代的组成的路径和回退边所能到达的最小的dfn值。如果可以到达的dfn值比u小,说明u可以通过其后代组成的路径和回退边到达u的祖先节点,即说明删除u之后,u的后代节点仍然可以到达u的祖先节点,即说明是连通的,故u不是割点。相反,若low[v] >= dfn[u],即说明v无法通过回退边和其它的路径到达u的祖先节点,删除u后则不连通,则可说明u是割点。

对于low[u],low[u] = min(dfn[u], dfn[v], low[v]) (v为u的所有子节点)。

判断割点的方法都有了,对于本题的求去掉割点后的连通分支数的问题就简单了。设sub[u]为u的子节点中无法到达u祖先的个数。当u为割点时,若u为树根,即u无祖先,显然图将被分成sub[u]块;若u不为树根,则将被分成sub[u]+1块,即比u为树根时多出了祖先所组成的一块。


POJ 1523 http://poj.org/problem?id=1523 

#include <algorithm>#include <iostream>#include <sstream>#include <cstring>#include <cstdio>#include <vector>#include <string>#include <bitset>#include <queue>#include <stack>#include <cmath>#include <ctime>#include <set>#include <map>using namespace std;// Macrotypedef long long LL;#define TIME cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s." << endl;#define IN freopen("/Users/apple/input.txt", "r", stdin);#define OUT freopen("/Users/apple/out.txt", "w", stdout);#define mem(a, n) memset(a, n, sizeof(a))#define rep(i, n) for(int i = 0; i < (n); i ++)#define repD(i, n) for(int i = (n); i; i --)#define REP(i, t, n) for(int i = (t); i < (n); i ++)#define REPD(i, t, n) for(int i = (n); i > (t); i --)#define FOR(i, t, n) for(int i = (t); i <= (n); i ++)#define FORD(i, t, n) for(int i = (n); i >= (t); i --)#define ALL(v) v.begin(), v.end()#define Min(a, b) a = min(a, b)#define Max(a, b) a = max(a, b)#define put(a) printf("%d\n", a)#define ss(a) scanf("%s", a)#define si(a) scanf("%d", &a)#define sii(a, b) scanf("%d%d", &a, &b)#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)#define VI vector<int>#define pb push_backconst int inf = 0x3f3f3f3f, N = 1e3 + 5, MOD = 1e9 + 7;// Macro endint T, cas = 0;int n, m;struct edge{int v, next;}e[5 * N];int ne, head[N];void InitEdge() {ne = 0;mem(head, -1);}void addEdge(int u, int v) {e[ne].v = v;e[ne].next = head[u];head[u] = ne ++;e[ne].v = u;e[ne].next = head[v];head[v] = ne ++;}int low[N], dfn[N], cut[N], sub[N];int rootsub, depth;// Impvoid Tarjan(int u, int fa) {low[u] = dfn[u] = ++ depth;for(int i = head[u]; i != -1; i = e[i].next) {int v = e[i].v;if(v == fa) continue;if(!dfn[v]) {Tarjan(v, u);Min(low[u], low[v]);if(low[v] >= dfn[u]) {if(u != 1) sub[u] ++;else rootsub ++;}} else Min(low[u], dfn[v]);}}int main(){#ifdef LOCAL    IN // OUT#endifint u, v;    while(si(u), u) {    InitEdge();    mem(dfn, 0);    si(v), addEdge(u, v);    int node = max(u, v);    while(si(u), u) {    si(v), addEdge(u, v);    node = max(u, v);    }    rootsub = ne = 0;    mem(sub, 0);    Tarjan(1, 1);    if(cas ++) puts("");    printf("Network #%d\n", cas);    if(rootsub > 1) sub[1] = rootsub - 1;    bool ok = false;    FOR(i, 1, node) {    if(sub[i]) {    ok = true;    printf("  SPF node %d leaves %d subnets\n", i, sub[i] + 1);    }    }    if(!ok) puts("  No SPF nodes");    }        return 0;}


0 0
原创粉丝点击