POJ3114 Countries in War 【强连通分量】

来源:互联网 发布:jdk源码有哪些值得买 编辑:程序博客网 时间:2024/05/17 06:12

题目链接:http://poj.org/problem?id=3114

题意:
有几个城市连通,如果几个城市互相连通,则他们传送信件不需要时间,否则就需要一些时间传送,现在问你某两个城市之间传送信件最少需要多长时间

题解:
最短路+强连通分量,两个模板直接搞定。
代码:

// memset 只能赋值 -1 和 0,其余用 fill() #include <queue>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int size = 505, size2 = 505*505, inf = 1 << 26;struct edges {    int to, next;} ed[size2];int n, m;int dfn[size], low[size], head[size], stack[size], instack[size], sccno[size], w[size][size];int mp[size][size];int dis[size], vis[size];// 最短路数组int cnt = 0, qcnt = 0, top = 0, scccnt = 0;void add(int u, int v) {    ed[cnt].to = v;    ed[cnt].next = head[u];    head[u] = cnt ++;}void init() {    cnt = qcnt = scccnt = top = 0;    memset(ed, 0, sizeof(ed));    memset(dfn, 0, sizeof(dfn));    memset(low, 0, sizeof(low));    memset(head, -1, sizeof(head));    memset(stack, 0, sizeof(stack));    memset(instack, 0, sizeof(instack));    memset(instack, 0, sizeof(instack));    memset(sccno, 0, sizeof(sccno));    memset(vis, 0, sizeof(vis));    for ( int i = 0; i <= n; i ++ ) for ( int j = 0; j <= n; j ++ ) w[i][j] = inf;    for ( int i = 0; i <= n; i ++ ) for ( int j = 0; j <= n; j ++ ) mp[i][j] = inf;}void Tarjan(int x) {    dfn[x] = low[x] = ++qcnt;    instack[x] = 1;    stack[++top] = x;    for ( int i = head[x]; i != -1; i = ed[i].next ) {        int y = ed[i].to;        if(!dfn[y]) {       // 检查是否被访问过            Tarjan(y);            low[x] = min(low[x], low[y]);        } else if(instack[y]) {            low[x] = min(low[x], low[y]);                            //== dfn[i]        }    }    if(dfn[x] == low[x]) {        int temp;        scccnt ++;        do {            temp = stack[top --];            instack[temp] = 0;            sccno[temp] = scccnt;        } while( temp != x );    }}void spfa(int s) {    for ( int i = 0; i <= n; i ++) dis[i] = inf;    dis[s] = 0;    queue<int> q;    q.push(s);    vis[s] = 1;     while(!q.empty()) {         int t = q.front(); q.pop();        vis[t] = 0;        for ( int i = 1; i <= scccnt; i ++ ) {            if(dis[i] > dis[t]+mp[t][i]) {                dis[i] = dis[t]+mp[t][i];                if(!vis[i]) {                    q.push(i);                    vis[i] = 1;                }            }        }    }}int main() {    // freopen("3114.in", "r", stdin);    while( scanf("%d %d", &n, &m), n ) {        init();        int a, b, c;        for ( int i = 1; i <= m; i ++ ) {            scanf("%d %d %d", &a, &b, &c);            add(a, b);            w[a][b] = min(w[a][b], c);        }        for ( int i = 1; i <= n; i ++ ) {            if(!dfn[i]) Tarjan(i);        }        for ( int i = 0; i <= n; i ++ ) mp[i][i] = 0;        for ( int i = 1; i <= n; i ++ ) {            for ( int j = 1; j <= n; j ++ ) {                if(i != j && sccno[i] != sccno[j] && w[i][j] != inf) {                    mp[sccno[i]][sccno[j]] = min(mp[sccno[i]][sccno[j]], w[i][j]);                }            }        }        int k;        scanf("%d", &k);        for ( int i = 0; i < k; i ++ ) {            int a, b;            scanf("%d %d", &a, &b);            if(sccno[a] == sccno[b]) {      // 属于一个强连通分量                puts("0");            } else {                spfa(sccno[a]);                if(dis[sccno[b]] < inf) printf("%d\n", dis[sccno[b]]);                else puts("Nao e possivel entregar a carta");            }        }        puts("");    }    return 0;}
0 0
原创粉丝点击