A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路。设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci。现在B国想找出一个路径切断方案,使中转站s不能到达中转站t,并且切断路径的代价之和最小。 小可可一眼就看出,这是一个求最小割的问题。但爱思考的小可可并不局限于此。现在他对每条单向道路提出两个问题: 问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断? 现在请你回答这两个问题。
Input
第一行有4个正整数,依次为N,M,s和t。第2行到第(M+1)行每行3个正 整数v,u,c表示v中转站到u中转站之间有单向道路相连,单向道路的起点是v, 终点是u,切断它的代价是c(1≤c≤100000)。 注意:两个中转站之间可能有多条道路直接相连。 同一行相邻两数之间可能有一个或多个空格。
Output
对每条单向边,按输入顺序,依次输出一行,包含两个非0即1的整数,分 别表示对问题一和问题二的回答(其中输出1表示是,输出0表示否)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。
思路:直接看大佬博客吧。。。。http://hzwer.com/3217.html
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 1e5 + 50;
int INF = 1e9;
struct Edge
{
int u, to, next, w, id;
} edge[maxn], data[maxn];
int k, head[maxn];
int n, m;
void add(int a, int b, int c){
edge[k].u = a;
edge[k].to = b;
edge[k].w = c;
edge[k].next = head[a];
head[a] = k++;
edge[k].u = b;
edge[k].to = a;
edge[k].w = 0;
edge[k].next = head[b];
head[b] = k++;
}
int dis[maxn];
int bfs(int s, int t){
queue<int> que;
for(int i = 0; i <= n; i++){
dis[i] = 0;
}
dis[s] = 1;
que.push(s);
while(que.size()){
int u = que.front();
que.pop();
if(u == t){
return 1;
}
for(int i = head[u]; i != -1; i = edge[i].next){
int to = edge[i].to;
int w = edge[i].w;
if(!dis[to] && w){
dis[to] = dis[u] + 1;
if(to == t){
return 1;
}
que.push(to);
}
}
}
return 0;
}
int cur[maxn];
int dfs(int u, int maxf, int t){
if(u == t){
return maxf;
}
int ret = 0;
for(int i = cur[u]; i != -1; i = edge[i].next){
cur[u] = i;
int to = edge[i].to;
int w = edge[i].w;
if(w && dis[to] == dis[u] + 1){
int mi = min(w, maxf - ret);
w = dfs(to, mi, t);
edge[i].w -= w;
edge[i ^ 1].w += w;
ret += w;
if(ret == maxf){
return ret;
}
}
}
return ret;
}
int Dinic(int s, int t){
int ans = 0;
while(bfs(s, t)){
for(int i = 0 ; i <= n; i++){
cur[i] = head[i];
}
ans += dfs(s, INF, t);
}
return ans;
}
void init(){
k = 0;
memset(head, -1, sizeof(head));
}
int dfn[maxn], low[maxn], ss[maxn], scc_id[maxn], in[maxn];
int tim, top, scc_cnt;
void Tarian(int u){
dfn[u] = low[u] = ++tim;
ss[++top] = u;
in[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next){
if(edge[i].w == 0){
continue;
}
int to = edge[i].to;
if(!dfn[to]){
Tarian(to);
low[u] = min(low[u], low[to]);
} else if(in[to]){
low[u] = min(low[u], dfn[to]);
}
}
if(low[u] == dfn[u]){
int x;
scc_cnt++;
do{
x = ss[top--];
scc_id[x] = scc_cnt;
in[x] = 0;
} while(x != u);
}
}
int main() {
init();
int s, t;
scanf("%d%d%d%d", &n, &m, &s, &t);
for(int i = 1; i <= m; i++){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
data[i].u = a;
data[i].to =b;
}
int res = Dinic(s, t);
for(int i = 1; i <= n; i++){
if(scc_id[i] == 0){
Tarian(i);
}
}
for(int i = 0; i < k; i += 2){
int u = edge[i].u;
int to = edge[i].to;
int ans1 = 0, ans2 =0;
if(edge[i].w == 0){
if(scc_id[u] != scc_id[to]){
ans1 = 1;
if((scc_id[u] == scc_id[s] && scc_id[to] == scc_id[t])){
ans2 = 1;
}
}
}
printf("%d %d\n", ans1, ans2);
}
}