/*
输入一个石油管道网,管道可以双向流通石油,即可以使用网络流计算最大流
输出网络最大流的关键路径,即降低某一管道的容量会使整个网络流降低。
首先可以尝试的方式是先计算最大流,然后遍历所有容量饱和的边,降低这些边的容量重新计算网络流和原网络流比较,太慢。
可以假象当前网络流已经达到最大,如果把一个饱和边的容量降低1,那么包和边的起点就会堆积1个流量而饱和边的终点会少了1流量,
如果在残留网络中,从这个起点到终点有一条容量大于等于1的增广路径,就不会影响整个网络流。如果只考虑在饱和边上最多只能降低1个流量
那么在残留网络中起点终点的增广路径就可以看做是起点终点在残留网络中的连通性,这样可以在残留网络上应用floyd求出节点之间的闭包,即连通性。
floyd会把连通饱和边的可用容量设置为1,在floyd应用完毕之后,管道中可用容量仍为0的就是关键路径。
*/
#include<fstream>
#include<iostream>
#define MAXNUM 10
#define MAXQUEUE 100
#define MAXWAY 10
using namespace std;
int G[MAXNUM][MAXNUM];
int n,m,s,t;
int tunnel[MAXWAY];
ifstream fin("input.txt");
void maxflow(){
int head,tail;
int i,j;
int v[MAXQUEUE];
int pre[MAXNUM];
int minflow[MAXNUM];
while(1){
memset(pre,0,sizeof(pre));
for(i=0;i<MAXNUM;i++)
minflow[i] = 9999;
head=0;
tail=0;
v[tail++] = s;
while(1){//寻找增广路
i = v[head++];
for(j=1;j<=n;j++){
if(G[i][j]&&!pre[j]){
pre[j] = i;
v[tail++] = j;
minflow[j] = min(minflow[i],G[i][j]);
//minflow = min(minflow,G[i][j]);不可以这样写,这样会把非路径上的路也算上
}
}
if(pre[t])
break;
if(head == tail)
break;
}
if(pre[t]){//扩增路径
i=pre[t];
j=t;
while(1){
cout<< i << " -> " << j << minflow[t] << endl;
G[i][j] -= minflow[t];
G[j][i] += minflow[t];
j=i;
i=pre[i];
if(j==s)
break;
}
}else
break;
cout << endl;
}
}
void solve(){//在残余网络上使用floyd求闭包
int i,j,k;
int cnt=0;
for(k=1;k<=n;k++){
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(G[i][k]&&G[k][j])
G[i][j] = 1;
}
for(i=0;i<m;i++){
j = tunnel[i]/(n+1);
k = tunnel[i]%(n+1);
if(!G[j][k]||!G[k][j]){
cnt++;
cout << j << " -> " << k << endl;
}
}
//cout << cnt;
}
int main(){
fin >> n >> m >> s >> t;
int i,x,y,g;
memset(G,0,sizeof(G));
for(i=0;i<m;i++){
fin >> x >> y >> g;
G[x][y] = g;
G[y][x] = g;
tunnel[i] = x*(n+1) + y;
}
maxflow();
solve();
}