这题做的好艰辛。。
先说题意:
给n个点 m条边 m条边中有单向边或双向边。题目保证给定的边一定构成一个连通图。
现在要求 尽可能多的重定向双向边为单向边。使图最后的结果为强连通图。输出所有双向边的情况(定向或者没定向的都要输出)

思路:

1.首先看哪些边一定不能重定向(就是原样输出的那些无向边)。先把所有的边看成无向边,求桥(tarjan)。把这些桥原样输出(这些桥一定是无向边,题目保证了图是连通的)(为什么桥不能重定向。因为重定向后图就不连通了)。
2.这些桥把许多个连通块连通起来。我们删掉这些桥。对这些连通块内部的无向边进行重定向
3.重定向边。参考tarjan算法。建立一颗dfs树。
1)如果无向边是树边。
如果u能到达u的祖先,也就是dfn[u]>=low[u],说明这条边是正确的 直接输出 u v 1。
如果u不能到达u的祖先,dfn[u]<low[u],说明这条边需要反向 输出 v u 1
2)如果无向边是回边。
说明方向是对的,因为借助这条边可以回到祖先。直接输出u v 1

这题做的好艰辛。。vector建图MLE 邻接矩阵建图MLE 邻接表才是真爱。AC

//author: CHC
//First Edit Time: 2014-07-06 14:29
//Last Edit Time: 2014-07-06 14:29
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
#define MAXN 2001
#define MAXM 2000000
int head[MAXN];
int tot;
struct Edge
{
int to,next;
}edge[MAXM];
void init(){
tot=0;
for(int i=0;i<MAXN;i++)head[i]=-1;
}
void Add_edge(int u,int v) {
edge[tot].next=head[u];
edge[tot].to=v;
head[u]=tot;
++tot;
}
int dfn[MAXN],low[MAXN],pre[MAXN],n,m;
int times=0,top;
char flag[MAXN][MAXN];
void tarjan_3(int u){
dfn[u]=low[u]=++times;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(!dfn[v]){
pre[v]=u;
tarjan_3(v);
low[u]=min(low[u],low[v]);
}
else if(pre[u]!=v)
low[u]=min(low[u],dfn[v]);
}
}
void solve(){
times=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(pre,0,sizeof(pre));
tarjan_3(1);
for(int i=1;i<=n;i++){
if(pre[i]>0&&dfn[pre[i]]<low[i]){
printf("%d %d %d\n",pre[i],i,2);
flag[pre[i]][i]=flag[i][pre[i]]=3;
}
}
//puts("");
top=times=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(pre,0,sizeof(pre));
void tarjan(int );
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
/*
puts("");
for(int i=1;i<=n;i++)
printf("%d ",dfn[i]);
puts("");
for(int i=1;i<=n;i++)
printf("%d ",low[i]);
puts("");
*/
}
void tarjan(int u){
dfn[u]=low[u]=++times;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(flag[u][v]==3)continue;
if(!dfn[v]){
pre[v]=u;
tarjan(v);
low[u]=min(low[u],low[v]);
if(flag[u][v]==2){
if(dfn[u]>=low[u]){
printf("%d %d %d\n",u,v,1);
flag[v][u]=0;
}
else {
printf("%d %d %d\n",v,u,1);
flag[u][v]=0;
}
}
}
else if(pre[u]!=v)
{
if(flag[v][u]==2)printf("%d %d %d\n",u,v,1);
flag[u][v]=0;
low[u]=min(low[u],dfn[v]);
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m)){
init();
memset(flag,0,sizeof(flag));
for(int i=0;i<m;i++){
int x,y;
int val;
scanf("%d%d%d",&x,&y,&val);
if(val==1){
Add_edge(x,y);
Add_edge(y,x);
flag[x][y]=1;
flag[y][x]=3;
}
else {
Add_edge(x,y);
Add_edge(y,x);
flag[x][y]=flag[y][x]=2;
}
}
solve();
}
return 0;
}
/*
5 5
1 3 2
1 2 2
2 5 2
4 5 1
3 4 2

5 5
1 2 2
1 3 2
2 5 2
4 5 1
3 4 2
*/