关键路径

/* 程序:求关节点(无向图) 
 * 分析:
 *         一个low数组,low[u] = min(low[v] | v in n) 
 *         若low[v] >= low[u],则u是关节点
 * 步骤:
 *        1.初始状态:一个无向图
 *               1,数据结构:vector<int>邻接表,vis数组,low数组,count序号全局变量 
 *              2,初始化:
 *         2.过程:
 *            1,判断根节点是否是关节点
                 1,若生成树的根节点有两可或两颗以上的子树,则此根节点必为关节点 
 *            2,深度优先搜索遍历邻接表,更新序号数组
 *            3,后序遍历
 *             4,判断:若low[v] >= low[u],则u是关节点,输出,否则更新low[u]值 
 */
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAX 1001

vector<int> g[MAX];
int vis[MAX];
int low[MAX];
int cnt; 
int ans;

bool judge(int u, int v, int a, int b) 
{
    if (a == u || b == u) return false;
    
    if (!vis[a] && !vis[b]) return false;
    else if (vis[a] && !vis[b]) 
        if (vis[a] > vis[u]) return true; 
    else if (!vis[a] && vis[b]) 
        if (vis[b] > vis[u]) return true;
    else {
        if (vis[a] < vis[u] && vis[b] > vis[u]) return true;
        else if (vis[a] > vis[u] && vis[b] < vis[u]) return true;    
        else return false;
    }
}

void dfs(int u, int fa, int a, int b)
{
    vis[u] = ++cnt;
    
    int _min = vis[u];
    vector<int>::iterator it;
    for (it = g[u].begin(); it < g[u].end(); it++) {
        int v = *it;
        if (!vis[v]) {
            // 后序遍历 
            dfs(v, u, a, b);  
            // 判断关节点 
            if (low[v] >= vis[u]) {    // 写成了low[v] >= low[u],明显错误,此时low[u]还没求出来呢 
                if (judge(u, v, a, b) == true) {
                    ans++;
                }
            }
            // 更新_min 
            _min = min(_min, low[v]);
        }
        else {
            if (v != fa)
                _min = min(_min, vis[v]);    // 写成了_min = min(_min, vis[v]);注意细节区别 
        } 
    }
    low[u] = _min; 
}

void  CriticalNode(int root, int n, int a, int b) 
{
    // 初始化
    memset(vis, 0, sizeof(vis));
    memset(low, 0, sizeof(low));
    cnt = 0;
    ans = 0;
    
    // 先遍历根节点第一个孩子节点 
    vector<int>::iterator it = g[root].begin();
    vis[root] = ++cnt;
    dfs(*it, root, a, b);
    
    // 判断根节点是否为关节点并遍历其余孩子节点 
    if (cnt < n) {
        // cout << root << endl;
        if (a == root || b == root) ; 
        else if (!vis[a] && vis[b]) ans++;
        else if (vis[a] && !vis[b]) ans++;
        
        for (++it; it < g[root].end(); it++) {
            if (!vis[*it]) dfs(*it, root, a, b);
        }
    }
}

void AddEdge(int u, int v)
{
    g[u].push_back(v);
    g[v].push_back(u);
}

int main()
{
    int n, m, u, v, a, b;
    while (cin >> n >> m) {
        for (int i = 0; i < n; i++) g[i].clear();
        for (int i = 0; i < m; i++) {
            cin >> u >> v;
            AddEdge(u - 1, v - 1);
        }
        
        cin >> a >> b;
        --a; --b;        // 细节,忘了做减一,前面记着了,后面的忘了,还是提醒和熟练得不够! 
        CriticalNode(0, n, a, b);
        
        // cout << cnt << endl;
        if (a == b || cnt < n) cout << -1 << endl;
        else cout << ans << endl;
    }
    return 0;
}

 

posted on 2014-03-21 23:51  Gddxz  阅读(188)  评论(0编辑  收藏  举报

导航