최소 절단 문제 에 대한 약간의 사고
다시 명확 하 게 정의 하 다
스 트림 네트워크 는 그림 에 정의 되 어 있 습 니 다.무방 향 도 를 유향 도로 뜯 어 내다.안 뜯 어도 돼.
최소 베 기 는 하나의 사 이 드 집합 \ (S, T) \), 점 을 \ (S, T = V - S \) 두 개의 집합 으로 나 눕 니 다.
최소 용량 \ (c (S, T) = \ sum {u \ in S} \ \ sum {v \ in T} c (u, v) \)
그래서 모든 변 을 삭제 하고 집중 한 후에 s 에서 t 까지 연결 되 지 않 습 니 다.최대 흐름 후 할 집 된 변 (s 에서 t 방향) 이 만 류 됩 니 다.
(t 에서 s 까지 꼭 그렇지 는 않다.)
최소 절단 의 유일 성
최대 흐름 후의 잔 량 네트워크 에서 만 류 된 변 은 반드시 가장 자 리 를 자 르 는 것 이 아니 라 가장 자 리 를 자 르 면 반드시 만 류 된다.
최소 절단 용량 은 절단 변 의 용량 과 최대 흐름 의 유량 과 같다.
최소 베 기 는 점 집합 이 유일 하 다 는 것 을 의미한다.
유일 성 판정:
강 한 연결 분량 (하나의 점 일 수 있 음) \ (u \) 이 존재 하여 잔 량 네트워크 에 s 에서 u 와 u 에서 t 까지 의 경로 가 없 음 을 만족 시 키 면 u 는 \ (S \) 또는 \ (T \) 에 분 배 될 수 있 으 며 최소 분할 이 유일 하지 않 습 니 다.
그래서 s 부터 bfs 를 시작 하고 t 에서 bfs 를 거꾸로 하 는 것 입 니 다.
전형 적 인 밤 1, 2, 1, 2, 3, 1, 2, 3, 1, 3, 4, 1.
scc 의 판정 방법 을 구하 십시오:
어떤 쪽 이 집중 할 수 있 는 지, 반드시 집중 할 수 있 는 지 를 판단 하 다.
scc 를 구하 고 판정 합 니 다.
scc 를 구 한 후 scc 사이 에 연 결 된 단 방향 변 은 한 방향 으로 만 류 되 기 때 문 임 을 알 수 있 습 니 다.
jcvb:
잔여 네트워크 에서 tarjan 을 뛰 어 다 니 며 모든 SCC 를 구하 고 id [u] 를 점 u 가 있 는 SCC 의 번호 로 기록 합 니 다.분명히 id [s] 가 있 습 니 다! =id [t] (그렇지 않 으 면 s 에서 t 까지 통로 가 있 고 계속 확대 할 수 있 습 니 다).
증명:
①
< = = 각 SCC 를 하나의 점 으로 축소 하여 얻 은 새 그림 은 만 류 변 만 포함 합 니 다.그러면 새 그림 의 모든 s - t 베 기 는 원래 그림 의 최소 베 기 에 대응 하고 그 중에서 id [u] 와 id [v] 를 자 르 는 것 을 선택 하면 증명 할 수 있 습 니 다.
② < = =: (u, v) 의 변 권 을 확대 한다 고 가정 하면 잔여 네트워크 에 s - > u - > v - > t 의 통로 가 나타 나 계속 넓 어 질 수 있 기 때문에 최대 유량 (즉 최소 용량) 이 커진다.이것 은 (u, v) 이 최소 절단 집중 에 반드시 나타 나 야 하 는 변 이라는 것 을 설명 한다.
PS: 무방 향도
역방향 아크 용량 은 c 이 므 로 두 번 추가 할 필요 가 없다.
QwQ 두 번 추가 가능 합 니 다.
템 플 릿 두 개
//zoj2587
#include
#include
#include
#include
using namespace std;
const int N = 1005, M = 20005, inf = 1e9;
int n, m, s, t;
struct edge {int v, ne, c, f;} e[M];
int cnt = 1, h[N];
inline void ins(int u, int v, int c) {
e[++cnt] = (edge) {v, h[u], c, 0}; h[u] = cnt;
e[++cnt] = (edge) {u, h[v], c, 0}; h[v] = cnt;
}
int cur[N], vis[N], d[N], head, tail, q[N];
bool bfs() {
memset(vis, 0, sizeof(vis));
head = tail = 1;
q[tail++] = s; d[s] = 0; vis[s] = 1;
while(head != tail) {
int u = q[head++];
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(!vis[v] && e[i].c > e[i].f) {
vis[v] = 1;
d[v] = d[u] + 1;
q[tail++] = v;
if(v == t) return true;
}
}
}
return false;
}
int dfs(int u, int a) { //printf("dfs %d %d
", u, a);
if(u==t || a==0) return a;
int flow = 0, f;
for(int &i=cur[u]; i; i=e[i].ne) {
int v = e[i].v;
if(d[v] == d[u]+1 && (f = dfs(v, min(a, e[i].c-e[i].f))) > 0) {
flow += f;
e[i].f += f;
e[i^1].f -= f;
a -= f;
if(a == 0) break;
}
}
if(a) d[u] = -1;
return flow;
}
int dinic() {
int flow = 0;
while(bfs()) {
for(int i=1; i<=n; i++) cur[i] = h[i];
flow += dfs(s, inf);
}
return flow;
}
int bfs2(int s) {
int ans = 1;
memset(vis, 0, sizeof(vis));
head = tail = 1;
q[tail++] = s; vis[s] = 1;
while(head != tail) {
int u = q[head++];
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(vis[v] || e[i].c==e[i].f) continue;
vis[v] = 1;
ans++;
q[tail++] = v;
}
}
return ans;
}
int bfs3(int s) {
int ans = 1;
memset(vis, 0, sizeof(vis));
head = tail = 1;
q[tail++] = s; vis[s] = 1;
while(head != tail) {
int u = q[head++];
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(vis[v] || e[i^1].c==e[i^1].f) continue;
vis[v] = 1;
ans++;
q[tail++] = v;
}
}
return ans;
}
int main() {
freopen("in", "r", stdin);
ios::sync_with_stdio(false); cin.tie(); cout.tie();
while(true) {
cin >> n >> m >> s >> t;
if(n == 0) break;
cnt = 1;
memset(h, 0, sizeof(h));
for(int i=1; i<=m; i++) {
int u, v, c;
cin >> u >> v >> c;
ins(u, v, c);
}
dinic();
int cnt1 = bfs2(s), cnt2 = bfs3(t);
if(cnt1 + cnt2 < n) cout << "AMBIGUOUS" << endl;
else cout << "UNIQUE" << endl;
}
}
//[AHOI2009]
#include
#include
#include
#include
using namespace std;
const int N = 4005, M = 6e4+5, inf = 1e9;
int n, m, s, t;
struct edge {int u, v, ne, c, f;} e[M<<1];
int cnt=1, h[N];
inline void ins(int u, int v, int c) {
e[++cnt] = (edge) {u, v, h[u], c, 0}; h[u] = cnt;
e[++cnt] = (edge) {v, u, h[v], 0, 0}; h[v] = cnt;
}
int cur[N], vis[N], d[N], head, tail, q[N];
bool bfs() {
memset(vis, 0, sizeof(vis));
head = tail = 1;
q[tail++] = s; d[s] = 0; vis[s] = 1;
while(head != tail) {
int u = q[head++];
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(!vis[v] && e[i].c > e[i].f) {
vis[v] = 1;
d[v] = d[u]+1;
q[tail++] = v;
if(v == t) return true;
}
}
}
return false;
}
int dfs(int u, int a) {
if(u==t || a==0) return a;
int flow = 0, f;
for(int &i=cur[u]; i; i=e[i].ne) {
int v = e[i].v;
if(d[v] == d[u]+1 && (f = dfs(v, min(a, e[i].c-e[i].f))) > 0) {
flow += f;
e[i].f += f;
e[i^1].f -= f;
a -= f;
if(a == 0) break;
}
}
if(a) d[u] = -1;
return flow;
}
int dinic() {
int flow = 0;
while(bfs()) {
for(int i=1; i<=n; i++) cur[i] = h[i];
flow += dfs(s, inf);
}
return flow;
}
int dfn[N], low[N], dfc, scc, belong[N], st[N], top;
void dfs(int u) {
dfn[u] = low[u] = ++dfc;
st[++top] = u;
for(int i=h[u]; i; i=e[i].ne) if(e[i].c > e[i].f) {
int v = e[i].v;
if(!dfn[v]) {
dfs(v);
low[u] = min(low[u], low[v]);
} else if(!belong[v])
low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u]) {
scc++;
while(true) {
int x = st[top--];
belong[x] = scc;
if(x == u) break;
}
}
}
int main() {
freopen("in", "r", stdin);
ios::sync_with_stdio(false); cin.tie(); cout.tie();
cin >> n >> m >> s >> t;
for(int i=1; i<=m; i++) {
int u, v, c;
cin >> u >> v >> c;
ins(u, v, c);
}
dinic();
for(int i=1; i<=n; i++) if(!dfn[i]) dfs(i);
//for(int i=1; i<=n; i++) printf("dfn %d %d %d
", i, dfn[i], belong[i]);
int a = belong[s], b = belong[t];
for(int i=1; i<=m; i++) {
int u = e[i<<1].u, v = e[i<<1].v;
if(e[i<<1].c == e[i<<1].f && belong[u] != belong[v]) cout << 1 << ' ';
else cout << 0 << ' ';
if(e[i<<1].c == e[i<<1].f && belong[u] == a && belong[v] == b) cout << 1 << '
';
else cout << 0 << '
';
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.