poj1515--Street Directions(边的双连通)

给一个无向图,要求变成强连通的有向图,需要保留哪些边。

边的双连通,对于桥保留两条边,其他的只保留一条边。求双连通的过程中记录保留边。

/*********************************************
Problem: 1515		User: G_lory
Memory: 232K		Time: 32MS
Language: C++		Result: Accepted
**********************************************/
#include <cstdio>
#include <cstring>
#include <iostream>
#define pk printf("KKK!\n");

using namespace std;

const int N = 1005;
const int M = N * N;

struct Edge {
    int from, to, next;
    int cut;
} edge[M];
int cnt_edge;
int head[N];
void add_edge(int u, int v)
{
    edge[cnt_edge].from = u;
    edge[cnt_edge].to = v;
    edge[cnt_edge].next = head[u];
    edge[cnt_edge].cut = 0;
    head[u] = cnt_edge++;
}

int dfn[N]; int idx;
int low[N];

int n, m;

void tarjan(int u, int pre)
{
    dfn[u] = low[u] = ++idx;
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (edge[i].cut) continue;
        edge[i].cut = 1;
        edge[i ^ 1].cut = -1;
        if (v == pre) continue;

        if (!dfn[v])
        {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (dfn[u] < low[v])
                edge[i].cut = edge[i ^ 1].cut = 1;
        }
        else low[u] = min(low[u], dfn[v]);
    }
}

void init()
{
    idx = cnt_edge = 0;
    memset(dfn, 0, sizeof dfn);
    memset(head, -1, sizeof head);
}

void solve()
{
    for (int i = 0; i < cnt_edge; ++i)
    if (edge[i].cut == 1)
    printf("%d %d\n", edge[i].from, edge[i].to);
}

int main()
{
    //freopen("in.txt", "r", stdin);
    int cas = 0;
    while (~scanf("%d%d", &n, &m))
    {
        if (n == 0 && m == 0) break;
        printf("%d\n\n", ++cas);
        int u, v;
        init();
        for (int i = 0; i < m; ++i)
        {
            scanf("%d%d", &u, &v);
            add_edge(u, v);
            add_edge(v, u);
        }
        tarjan(1, -1);
        solve();
        printf("#\n");
    }
    return 0;
}

  

时间: 2024-12-27 18:50:36

poj1515--Street Directions(边的双连通)的相关文章

POJ 1515 Street Directions --一道连通题的双连通和强连通两种解法

题意:将一个无向图中的双向边改成单向边使图强连通,问最多能改多少条边,输出改造后的图. 分析: 1.双连通做法: 双连通图转强连通图的算法:对双连通图进行dfs,在搜索的过程中就能按照搜索的方向给所有边定向,其中桥不能改造,只能保留双向边. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #includ

【图论】双连通总结

双连通总结 这类问题分为,边-双连通,点-双连通 边双连通 边双连通,求出来后,连接没一个双连通的分量的就是割边,因此可以缩点成一棵树,把问题转化为在树上搞,割边的定义为:去掉这条边后图将不连通 基本这类题都一个解法,求双连通分量,然后缩点成树,进行操作 或者就是直接要求割边,做跟割边相关的操作 模板: #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #

UVA 610 - Street Directions(割边)

UVA 610 - Street Directions 题目链接 题意:给定一个无向图,要求把尽可能多的边定向,使得形成一个强连通图,输出定向后的图,不能定向的边就变成两条有向边 思路:找出割边,只有割边是需要定成两条的,其他的双连通分量中,边肯定都可以定向,然后在dfs不经过割边打印路径,最后在打印出割边(拆成两条) 代码: #include <cstdio> #include <cstring> #include <vector> using namespace s

UVALive 5412 Street Directions

Street Directions Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ID: 541264-bit integer IO format: %lld      Java class name: Main According to the Automobile Collision Monitor (ACM), most fatal traffic acc

HDU 4005 The war(双连通好题)

HDU 4005 The war 题目链接 题意:给一个连通的无向图,每条边有一个炸掉的代价,现在要建一条边(你不不知道的),然后你要求一个你需要的最少代价,保证不管他建在哪,你都能炸掉使得图不连通 思路:炸肯定要炸桥,所以先双连通缩点,得到一棵树,树边是要炸的,那么找一个最小值的边,从该边的两点出发,走的路径中,把两条包含最小值的路径,的两点连边,形成一个环,这个环就保证了最低代价在里面,除了这个环以外的最小边,就是答案,这样的话,就利用一个dfs,搜到每个子树的时候进行一个维护即可 代码:

ACM学习-图双连通子图

// ACM学习-割点和桥.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<queue> #include<vector> #include<algorithm> using namespace std; const int v = 13; int edge[v][v] = { { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0

双连通问题

一些定义: 割点集合(割集):在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合. 点连通度:最小割点集合中的顶点数. 割边集合:如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合. 边连通度:最小割边集合中的边数. 点双连通:如果一个无向连通图的点连通度大于1,则称该图是点双连通的,简称双连通或重连通.割点:一个图有割点,当且仅当这个图的点连通度为1,则割点集合的唯一元素被称为

图的连通性问题的小结 (双连通、2-SAT)

图的连通性问题包括: 1.强连通分量. 2.最小点基和最小权点基. 3.双连通. 4.全局最小割. 5.2-SAT 一.强连通分量 强连通分量很少单独出题,一般都是把求强连通分量作为缩点工具. 有三种算法: 1.Kosaraju算法.对原图和反图分别进行一次深度优先搜索. 2.Tarjan算法.用了时间戳. 3.Garbow算法.与Tarjan算法是同一思想,但更精妙. 三种算法的模版我已经贴过了  http://www.cnblogs.com/Potato-lover/p/3956604.ht

poj3352Road Construction 边双连通+伪缩点

/* 对于边双连通分支,求法更为简单.只需在求出所有的桥以后,把桥边删除,原图变成了多个连通块,则每个连通块就是一个边双连通分支.桥不属于任何 一个边双连通分支,其余的边和每个顶点都属于且只属于一个边双连通分支. 一个有桥的连通图,如何把它通过加边变成边双连通图?方法为首先求出所有的桥, 然后删除这些桥边,剩下的每个连通块都是一个双连通子图.把每个双连通子图收缩为一个顶点, 再把桥边加回来,最后的这个图一定是一棵树,边连通度为1. 统计出树中度为1的节点的个数,即为叶节点的个数,记为leaf.则