Your job is to create a new traffic system in the town. You have to determine the direction of traffic for as many two-way streets as possible and make sure that it is still possible to travel both ways between any two intersections.
Write a program that:
- reads a description of the street system in the town from the standard input,
- for each two-way street determines one direction of traffic or decides that the street must remain two-way,
- writes the answer to the standard output.
Input
The first line of the input contains two integers n and m, where 2n2000 and n - 1mn(n - 1)/2. Integer n is the number of intersections in the town and integer m is the number of streets.Each of the next m lines contains three integers a, b and c, where 1an, 1bn, ab and c belongs to {1, 2}. If c = 1 then intersections a and b are connected by an one-way street from a to b. If c = 2 then intersections a and b are connected by a two-way street. There is at most one street connecting any two intersections.
Output
The output contains exactly the same number of lines as the number of two-way streets in the input. For each such street (in any order) the program should write three integers a, b and c meaning, the new direction of the street from a to b ( c = 1) or that the street connecting a and b remains two-way ( c = 2). If there are more than one solution with maximal number of one-way streets then your program should output any of them but just one.Sample Input
4 4 4 1 1 4 2 2 1 2 1 1 3 2
Sample Output
2 4 1 3 1 2
题意:给出一个既有有向边又有无向边的强连通的图。要你让尽可能多的无向边变成有向边,使得这个图还是强连通。
思路:好吧。。我自己没想出来。虽然基本上能想到桥肯定是保留成原有的状态的。因为如果删掉了一个方向,肯定不是强连通的。然后接下来是不是不是桥的就一定能只保留一个方向使得图仍然是强连通呢?。。。这里我自己没想明白。看了题解之后大概明白了,我们找出桥之后,会得到各个边-双联通分量。我们随便取一个连通分量看看,假设他是一个强连通分量,我们把其中一个无向边删掉,那么这个强连通最多就变成了两个强连通分量A和B,那么一定会有一条边是A到B,或者B到A,否则的话,这里面就不是双连通分量了。不妨设是A到B,那么我们无向边的方向只需要是B到A,那么这个图还是强连通。所以对于不是桥的无向边我们一定能让他只保留一个方向。
那么做法是在dfs的时候,把时间戳记下来,如果对于无向边(u,v)有pre[u]<low[v]表明子孙不能回来了,我们就把这个无向边的方向标记为v->u,否则的话,就按照dfs的顺序就可以了。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<cstring>
#include<vector>
using namespace std;
#define mp make_pair
const int maxn = 2000 + 5;
int n, m;
short dfn, pre[maxn], low[maxn];
bool isbridge[maxn][maxn];
vector<short> G[maxn];
vector<short> g[maxn];
bool twoway[maxn][maxn];
void dfs1(int u, int fa)
{
pre[u] = low[u] = ++dfn;
for (int i = 0; i < G[u].size(); ++i)
{
int v = G[u][i];
if (v == fa) continue;
if (!pre[v])
{
dfs1(v, u);
low[u] = min(low[u], low[v]);
if (low[v]>pre[u]) isbridge[u][v] = isbridge[v][u] = true;
}
else if (pre[v] < pre[u])
low[u] = min(low[u], pre[v]);
}
}
void dfs2(int u, int fa)
{
pre[u] = low[u] = ++dfn;
for (int i = 0; i < g[u].size(); ++i)
{
int v = g[u][i];
if (isbridge[u][v] || v==fa) continue;
if (!pre[v])
{
dfs2(v, u);
low[u] = min(low[u], low[v]);
if (twoway[u][v])
{
if (pre[u] < low[v]) twoway[u][v] = false;
else twoway[v][u] = false;
}
}
else {
if (twoway[u][v]) twoway[v][u] = false;
low[u] = min(low[u], pre[v]);
}
}
}
void input()
{
memset(twoway, 0, sizeof(twoway));
for (int i = 1; i <= n; ++i) G[i].clear(), g[i].clear();
while (m--)
{
int u, v, type;
scanf("%d%d%d", &u, &v, &type);
G[u].push_back(v);
G[v].push_back(u);
g[u].push_back(v);
if (type == 2) {
g[v].push_back(u);
twoway[u][v] = twoway[v][u] = true;
}
}
}
void solve()
{
memset(pre, 0, sizeof(pre));
memset(low, 0, sizeof(low));
dfn = 0;
memset(isbridge, 0, sizeof(isbridge));
dfs1(1, -1);
memset(pre, 0, sizeof(pre));
memset(low, 0, sizeof(low));
for (int i = 1; i <= n; ++i) if (!pre[i]) {
dfn = 0;
dfs2(i,-1);
}
for (int u = 1; u <= n; ++u)
{
for (int v = u+1; v <= n; ++v)
{
if (isbridge[u][v]) { printf("%d %d 2\n", u, v); continue; }
if (twoway[u][v] && !twoway[v][u]) printf("%d %d 1\n", u, v);
else if (twoway[v][u] && !twoway[u][v]) printf("%d %d 1\n", v, u);
}
}
}
int main()
{
while (~scanf("%d%d", &n, &m))
{
input();
solve();
}
}