aboutsummaryrefslogblamecommitdiff
path: root/dom.c
blob: 7fbd948f5ce45b69fb0b2c27de41cfee31acd1c1 (plain) (tree)


























































































































































                                                                     
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN 1000
#define MAX_HASH 1021
typedef struct Edge Edge;
typedef struct Set Set;
typedef Set *Set_t;
typedef struct SetNode {
        int val;
        struct SetNode *next;        
} SetNode;
struct Set {
    SetNode *head[MAX_HASH];
};

Set_t set_create() {
    Set_t set = (Set_t)malloc(sizeof(Set));
    memset(set->head, 0, sizeof set->head);
    return set;
}

int set_belongs(Set_t set, int val) {
    SetNode *p;
    for (p = set->head[val % MAX_HASH]; p; p = p->next)
        if (p->val == val) return 1;
    return 0;
}

void set_push(Set_t set, int val) {
    SetNode *p = (SetNode*)malloc(sizeof(SetNode));
    int hv = val % MAX_HASH;
    p->next = set->head[hv];
    p->val = val;
    set->head[hv] = p;
}

struct Edge {
    int to;
    Edge *next;
} *head[MAXN], *rhead[MAXN];

typedef struct DFNode DFNode;
struct DFNode {
    int id;
    DFNode *next;
};

void add_edge(int a, int b, Edge **head) {
    Edge *p = (Edge*)malloc(sizeof(Edge));
    p->to = b;
    p->next = head[a];
    head[a] = p;
}
int dom[MAXN], ord[MAXN], vis[MAXN], par[MAXN];
int n, n0, m;
DFNode *df[MAXN];
Set_t dfset[MAXN];

void dfs(int u, int v) {
    static int ocnt = 0;
    Edge *e;
    if (vis[u] != -1) return;
    par[u] = v;
    vis[u] = 0;
    for (e = head[u]; e; e = e->next)
        dfs(e->to, u);
    vis[u] = ocnt;
    ord[ocnt++] = u;
}

int intersect(int b1, int b2) {
    while (b1 != b2)
        if (b1 < b2) b1 = dom[b1];
        else b2 = dom[b2];
    return b1;
}

int main() {
    int i;
    int ch = 1; 
    scanf("%d %d %d", &n, &m, &n0);
    for (i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        add_edge(a, b, head);
        add_edge(b, a, rhead);
    }
    for (i = 0; i < n; i++)
        vis[i] = dom[i] = -1;
    dfs(n0, -1);
    for (i = 0; i < n; i++)
        printf("%d ", ord[i]); puts("");
    dom[vis[n0]] = vis[n0];
    while (ch)
    {
        int i;
        ch = 0;
        for (i = n - 2; i >= 0; i--)
        {
            int id = ord[i];
            Edge *e = rhead[id];
            int new_idom = vis[par[id]];
            for (; e; e = e->next)
            {
                int p = e->to;
                if (p == new_idom) continue;
                if (dom[vis[p]] != -1)
                    new_idom = intersect(vis[p], new_idom);
            }
            if (dom[i] != new_idom)
            {
                ch = 1;
                dom[i] = new_idom;
            }
        }
        for (i = 0; i < n; i++)
            printf("%d ", ord[dom[vis[i]]]); puts("");
    }
    for (i = 0; i < n; i++)
    {
        dfset[i] = set_create();
        df[i] = NULL;
    }
    for (i = 0; i < n; i++)
        if (rhead[i] && rhead[i]->next)
        {
            Edge *p = rhead[i];
            for (; p; p = p->next)
            {
                int runner = p->to;
                while (vis[runner] != dom[vis[i]])
                {
                    if (!set_belongs(dfset[runner], i))
                    {
                        DFNode *np = (DFNode*)malloc(sizeof(DFNode));
                        np->id = i;
                        np->next = df[runner];
                        set_push(dfset[runner], i);
                        df[runner] = np;
                    }
                    runner = ord[dom[vis[runner]]];
                }
            }
        }
    for (i = 0; i < n; i++)
    {
        DFNode *p = df[i];
        printf("%d: ", i);
        for (; p; p = p->next)
            printf("%d ", p->id); puts("");
    }
    return 0;
}