poj1515 有向图专无向图

题目链接:

http://poj.org/problem?id=1515

Street Directions

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 1296 Accepted: 652 Special Judge

Description

According to the Automobile Collision Monitor (ACM), most fatal traffic accidents occur on two-way streets. In order to reduce the number of fatalities caused by traffic accidents, the mayor wants to convert as many streets as possible into one-way streets. You have been hired to perform this conversion, so that from each intersection, it is possible for a motorist to drive to all the other intersections following some route. 

You will be given a list of streets (all two-way) of the city. Each street connects two intersections, and does not go through an intersection. At most four streets meet at each intersection, and there is at most one street connecting any pair of intersections. It is possible for an intersection to be the end point of only one street. You may assume that it is possible for a motorist to drive from each destination to any other destination when every street is a two-way street. 

Input

The input consists of a number of cases. The first line of each case contains two integers n and m. The number of intersections is n (2 <= n <= 1000), and the number of streets is m. The next m lines contain the intersections incident to each of the m streets. The intersections are numbered from 1 to n, and each street is listed once. If the pair i j is present, j i will not be present. End of input is indicated by n = m = 0. 

Output

For each case, print the case number (starting from 1) followed by a blank line. Next, print on separate lines each street as the pair i j to indicate that the street has been assigned the direction going from intersection i to intersection j. For a street that cannot be converted into a one-way street, print both i j and j i on two different lines. The list of streets can be printed in any order. Terminate each case with a line containing a single `#' character. 

Note: There may be many possible direction assignments satisfying the requirements. Any such assignment is acceptable. 

Sample Input

7 10
1 2
1 3
2 4
3 4
4 5
4 6
5 7
6 7
2 5
3 6
7 9
1 2
1 3
1 4
2 4
3 4
4 5
5 6
5 7
7 6
0 0

Sample Output

1

1 2
2 4
3 1
3 6
4 3
5 2
5 4
6 4
6 7
7 5
#
2

1 2
2 4
3 1
4 1
4 3
4 5
5 4
5 6
6 7
7 5
#

Source

East Central North America 1998

题目大意:

给你n个点的图,m个双向图,(n个点m条无向边(保证图连通)

问:把尽量多的无向边变成有向边,使得最终图保持强连通的特性。

思路:保留桥的双向连通性(输出两次),其余的边变成有向边(输出一次)

注意题目中的i^1的使用 

This is the code

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x7f7f7f7f      //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。;
const int dr[]= {0, -1, 1,0, -1, -1, 1, 1};
const int dc[]= { 1, 0, 0, -1,-1, 1, -1, 1};
const int maxn=1050;
const int maxm=maxn*maxn;
int head[maxn];
int dfn[maxn];
int low[maxn];
int tol;
int clock_time;

struct node
{
    int from,to,next;
    int cnt;//表示是否是桥
    node(){}
    node(int from,int to,int next):from(from),to(to),next(next)
    {
        cnt=0;//未进行处理
    }
}edge[maxm];

void init(int n)
{
    for(int i=0;i<=n;++i)
    {
        head[i]=-1;
        dfn[i]=0;
    }
    tol=clock_time=0;
}

void addEdge(int u,int v)
{
    edge[tol].from=u;
    edge[tol].to=v;
    edge[tol].next=head[u];
    edge[tol].cnt=0;
    head[u]=tol++;
}

void tarjan(int u,int pre)
{
    low[u]=dfn[u]=++clock_time;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(edge[i].cnt)
            continue;
        edge[i].cnt=1;//1表示能够输出
        edge[i^1].cnt=-1;//-1表示不能够输出,如果求出edge[i]是桥的话,下面会将两个都设为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].cnt = edge[i^1].cnt = 1;//桥需要输出两次
        }
        else
            low[u]=min(low[u],dfn[v]);
    }
}

int main()
{
    int t=0;
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m)
            break;
        ++t;
        init(n);
        for(int i=0;i<m;++i)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addEdge(u,v);
            addEdge(v,u);
        }
        tarjan(1,-1);
        printf("%d\n\n",t);
        for(int i=0;i<tol;++i)
            if(edge[i].cnt==1)//判断输出
                printf("%d %d\n",edge[i].from,edge[i].to);
        printf("#\n");
    }
    return 0;
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值