POJ - 1515 Street Directions(无向图变有向图)

题目大意:给出一张无向图,任意两点可相互到达,现在要求你将这张无向图变成有向图,且改变之后任意两点还是可相互到达的

解题思路:桥的话肯定是要保留双向的,所以可以在dfs的时候把桥标记出来,顺便在dfs的时候标记一下使用的是哪条边即可

#include <cstdio>
#include <cstring>

#define N 1010
#define M 1000010
#define min(a,b) ((a) < (b) ? (a) : (b))

struct Edge{
    int from, to, next, flag;
}E[M];

int head[N], pre[N], lowlink[N];
int tot, n, m, dfs_clock;

void AddEdge(int u, int v) {
    E[tot].from = u;
    E[tot].to = v;
    E[tot].flag = 0;
    E[tot].next = head[u];
    head[u] = tot++;
}

void init() {
    memset(head, -1, sizeof(head));
    tot = 0;

    int u, v;
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &u, &v);
        AddEdge(u, v);
        AddEdge(v, u);
    }
}

void dfs(int u, int fa) {
    pre[u] = lowlink[u] = ++dfs_clock;

    int v;
    for (int i = head[u]; i != -1; i = E[i].next) {
        v = E[i].to;
        if (E[i].flag) continue;
        E[i].flag = 1;
        E[i ^ 1].flag = -1;
        if (!pre[v]) {
            dfs(v, u);
            lowlink[u] = min(lowlink[u], lowlink[v]);
            if (lowlink[v] > pre[u])
                E[i ^ 1].flag = 1;
        }
        else if (v != fa)
            lowlink[u] = min(lowlink[u], pre[v]);
    }

}

int cas = 1;
void solve() {
    memset(pre, 0, sizeof(pre));
    dfs_clock = 0;

    for (int i = 1; i <= n; i++)
        if (!pre[i])
            dfs(i, -1);

    printf("%d\n\n", cas++);
    int u, v;
    for (int i = 0; i < tot; i++) {
        u = E[i].from;
        v = E[i].to;
        if (E[i].flag == 1)
            printf("%d %d\n", u, v);
    }
    printf("#\n");
}

int main() {
    while (scanf("%d%d", &n, &m) != EOF && n + m) {
        init();
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-14 11:54:11

POJ - 1515 Street Directions(无向图变有向图)的相关文章

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

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

POJ 1515 Street Directions

题意: 一幅无向图  将尽量多的无向边定向成有向边  使得图强连通  无向图保证是连通的且没有重边 思路: 桥必须是双向的  因此先求边双连通分量  并将桥保存在ans中 每一个双连通分量内的边一定都能够变成有向边(毕竟是圈组成的图) 边的定向方式分两种: 1.对于树枝边u->v  假设low[v]>dfn[u]说明v回不到u上面去  所以ans应该是v->u的边  否则是u->v 2.对于逆向边  应该全在ans中  由于对于dfs树而言  这样的边利于low减小 代码: #in

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

UVA 610 - Street Directions(割边)

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

poj 1386 Play on Words(有向图欧拉路+并查集)

题目链接:http://poj.org/problem?id=1386 思路分析:该问题要求判断单词是否能连接成一条直线,转换为图论问题:将单词的首字母和尾字母看做一个点,每个单词描述了一条从首字母指向尾字母的有向边, 则则所有的单词构成了一个有向图,问题变为判断该有向图中是否存在一条欧拉路:有向图中存在欧拉路的两个充分必要条件为:该图是联通的并且所有的点的入度等于出度或者只存在两个点的入度与出度不等,一个点的入度=出度+1,另一个点的入度=出度-1: 代码如下: #include <cstdi

poj 3177 &amp; 3352 【无向图双连通分量Tarjan】

题目:poj 3177 & 3352 题意:大概意思就是给你一个无向图,让你添加最少的边,让所有点都双连通. 分析:双连通的定义就是任意两个点至少有两条路可达. 其实做法跟添加最少边强连通一样,先对图中已经双连通的缩点,然后重新编号. 这就是著名的Tanjan算法. 通过搜索的思想对所有存在环的边遍相同的号 如果要让所有的点双连通,那么对于缩点后的图中如果度数为 1 的话,这些边肯定要连接到其他的点才能双连通,而题目要求添加最少,所以连接到其他度数也为 1 的点是最优的,那么答案就是(odd+1

poj 2914 Minimum Cut 无向图最小边割

题意: 求无向图的全局最小边割. 分析: stoer-wagner模板. 代码: //poj 2914 //sep9 #include <iostream> using namespace std; const int maxN=512; int g[maxN][maxN]; int b[maxN],dist[maxN]; int n,m; int Min_Cut_Phase(int ph,int &x,int &y) { int i,j,t; t=1; b[1]=ph; fo

poj 2117 Electricity 【无向图求割点】【求去掉一个点后 图中最多的BCC数目】

Electricity Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4597   Accepted: 1515 Description Blackouts and Dark Nights (also known as ACM++) is a company that provides electricity. The company owns several power plants, each of them sup

POJ 1515 双联通分量

点击打开链接 题意:给一个联通的无向图,然后问你将其中的边变为有向的,加边使其变成有向的联通图 思路:若无向图有双联通分量,那么这个分量里的元素可以变成有向图的强联通,这应该很好看出来,然后需要加的边是什么呢,就是这个图上的桥呗,是桥的话变成有向的就要加一条边,然后剩下的无向图的双联通分量可以用dfs搜一下,边搜边输出就可以了,将桥记录下来遇到桥的时候特殊处理一下,然后双联通分量里的边每一条只能走一次,将走得边和反向边标记一下就行了  PS:vector写这样反向边的真是麻烦 #include