题目链接:
http://poj.org/problem?id=1515
Street Directions
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. 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. Sample Input Sample Output Source |
题目大意:
给你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;
}