/**************************************************************
Problem: 1797
User: gaotianyu1350
Language: C++
Result: Accepted
Time:452 ms
Memory:6324 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <queue>
using namespace std;
const long long MAXN = 5000;
const long long MAXM = 120100;
const long long INF = ((unsigned long long)1<<63) - 1;
long long point[MAXN], nxt[MAXM], f[MAXM], v[MAXM], flow[MAXM], cap[MAXM];
long long lastedge[MAXN], deep[MAXN], num[MAXN], cur[MAXN];
long long tot, n, m, start, end;
bool check[MAXN];
long long dfsTime[MAXN] = {0}, lessTime[MAXN] = {0}, cct[MAXN] = {0}, st[MAXN] = {0};
long long nowTime = 0, cnt = 0, top = 0;
inline long long min(long long a, long long b)
{
return a < b ? a : b;
}
inline long long max(long long a, long long b)
{
return a > b ? a : b;
}
inline void clear()
{
memset(point, -1, sizeof(point));
memset(nxt, -1, sizeof(nxt));
tot = -1;
}
inline void addedge(long long x, long long y, long long theCap)
{
tot++;
nxt[tot] = point[x];
point[x] = tot;
v[tot] = y;
f[tot] =x;
cap[tot] = theCap;
tot++;
nxt[tot] = point[y];
point[y] = tot;
v[tot] = x;
f[tot] = y;
cap[tot] = 0;
}
void bfs(long long s, long long t)
{
queue<int> q;
while (!q.empty()) q.pop();
memset(check, 0, sizeof(check));
memset(deep, 0, sizeof(deep));
check[t] = true;
q.push(t);
while (!q.empty())
{
long long now = q.front();
q.pop();
for (long long temp = point[now]; temp != -1; temp = nxt[temp])
{
long long tt = temp ^ 1;
if (!check[v[temp]] && flow[tt] < cap[tt])
{
check[v[temp]] = true;
deep[v[temp]] = deep[now] + 1;
q.push(v[temp]);
}
}
}
}
inline long long addflow(long long s, long long t)
{
long long ans = INF;
long long now = t;
while (now != s)
{
long long temp = lastedge[now];
ans = min(ans, cap[temp] - flow[temp]);
now = v[temp ^ 1];
}
now = t;
while (now != s)
{
long long temp = lastedge[now];
flow[temp] += ans;
flow[temp ^ 1] -= ans;
now = v[temp ^ 1];
}
return ans;
}
long long isap(long long s, long long t)
{
long long ans = 0;
long long now = s;
bfs(s, t);
memset(num, 0, sizeof(num));
for (long long i = 1; i <= n; i++)
{
num[deep[i]]++;
cur[i] = point[i];
}
while (deep[s] < n)
{
if (now == t)
{
ans += addflow(s, t);
now = s;
}
bool isok = false;
for (long long temp = cur[now]; temp != -1; temp = nxt[temp])
if (deep[now] == deep[v[temp]] + 1 && flow[temp] < cap[temp])
{
isok = true;
lastedge[v[temp]] = temp;
cur[now] = temp;
now = v[temp];
break;
}
if (!isok)
{
long long minn = n - 1;
for (long long temp = point[now]; temp != -1; temp = nxt[temp])
if (flow[temp] < cap[temp])
minn = min(minn, deep[v[temp]]);
if (--num[deep[now]] == 0) break;
num[deep[now] = minn + 1]++;
cur[now] = point[now];
if (s != now) now = v[lastedge[now] ^ 1];
}
}
return ans;
}
void tarjan(long long now)
{
dfsTime[now] = lessTime[now] = ++nowTime;
st[++top] = now;
for (long long temp = point[now]; temp != -1; temp = nxt[temp])
if (flow[temp] < cap[temp])
{
long long tar = v[temp];
if (!dfsTime[tar])
{
tarjan(tar);
lessTime[now] = min(lessTime[now], lessTime[tar]);
}
else if (!cct[tar])
lessTime[now] = min(lessTime[now], dfsTime[tar]);
}
if (dfsTime[now] == lessTime[now])
{
cnt++;
while (1)
{
cct[st[top--]] = cnt;
if (st[top + 1] == now) break;
}
}
}
int main()
{
//freopen("input.txt", "r", "stdin");
clear();
scanf("%lld%lld%lld%lld", &n, &m, &start, &end);
for (long long i = 1; i <= m; i++)
{
long long x, y, z;
scanf("%lld%lld%lld", &x, &y, &z);
addedge(x, y, z);
}
isap(start, end);
for (long long i = 1; i <= n; i++)
if (!dfsTime[i])
tarjan(i);
for (long long i = 1; i <= m; i++)
{
long long now = i * 2 - 2;
if (flow[now] == cap[now] && cct[f[now]] != cct[v[now]])
{
if (cct[f[now]] == cct[start] && cct[v[now]] == cct[end])
printf("1 1\n");
else
printf("1 0\n");
}
else
printf("0 0\n");
}
}
[BZOJ1797][AHOI2009][最大流][強連通分量]Mincut最小割
[Problem Description]
A,B兩個國家正在交戰,其中A國的物資運輸網中有N箇中轉站,M條單向道路。設其中第i (1≤i≤M)條道路連接了vi,ui兩個中轉站,那麼中轉站vi可以通過該道路到達ui中轉站,如果切斷這條道路,需要代價ci。現在B國想找出一個路徑切斷方案,使中轉站s不能到達中轉站t,並且切斷路徑的代價之和最小。 小可可一眼就看出,這是一個求最小割的問題。但愛思考的小可可並不侷限於此。現在他對每條單向道路提出兩個問題:
問題一:是否存在一個最小代價路徑切斷方案,其中該道路被切斷? 問題二:是否對任何一個最小代價路徑切斷方案,都有該道路被切斷? 現在請你回答這兩個問題。
[Algorithm]
最大流,強連通分量
[Analysis]
先跑最大流是肯定的。然後在殘留網絡裏跑強連通分量。一個原圖中的邊,如果滿流且兩點所在的強連通分量不同,則可能出現在最小割中,如果兩個強連通分量一個包含s,一個包含t,則一定出現在最小割中
[Pay Attention]
發現自己真是越來越手殘了……
[Code]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.