タイトル:羅区P4126 [AHOI2009]最小カット
アイデア:
結論タイトル
残渣を、uがあるtarjan全てSCC、と表さID [U] SCC番号ポイントを取得するためにネットワーク上で実行しました。明らかにIDがある[S]!= ID [ T]( TまたはSを増強継続して、アクセス権を持っています)。
いずれかのフルフローエッジに対して(u、v)が、(uは 、v)は、一定の最小濃度カット中に存在することができる場合にのみID [U] = ID [V ] ;!
いずれかのフルフローエッジについて(U、 V)、(u、v)は、最小カットセットに現れなければならない場合にのみID [U] == ID [S ] とID [V] == ID [T ]。
:それはあることを証明
①SCCは唯一のフルフローを含む側に新しいマップを取得するために、各ポイントに縮小しました。次に、新しいマップは、任意のSTカットピクチャは[V]カットプルーフを切断することができるID [U]とIDを取るいずれかの最小カットに対応します。
②増加(U、V)が増強続けることができるように右側、次いで残渣を、通路のネットワークS-> U-> V-> Tで発生する、フロー(すなわち、最小容量カット)の、最大流量を想定それは増加します。即ち、この説明は、(u、v)は最先端の最小濃度が存在しなければならないです。
上記の説明では、説明することはあまりないので、より良い解釈を考えていない、比較的明確で、限られた思考となっています。
符号の残量が逆弧が存在するコンフィギュレーション0のエッジの最大流量よりもすべてのエッジの重みより大きな仕上げた後、図の構造に示される実際のネットワークを指すことに留意されたいです。
コード:
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+5,inf=0x3f3f3f3f;
int n,m,s,t,d[N];
int tim,tp,scc_num,st[N],dfn[N],low[N],belong[N];
int Top=1,ver[N],val[N],nxt[N],head[N];
inline void add(int u,int v,int w){
ver[++Top]=v;val[Top]=w;nxt[Top]=head[u];head[u]=Top;
ver[++Top]=u;val[Top]=0;nxt[Top]=head[v];head[v]=Top;
}
bool bfs(){
for(int i=1;i<=n;++i) d[i]=0;
queue<int> q;
q.push(s);
d[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=nxt[i]){
int v=ver[i];
if(val[i]&&!d[v]){
d[v]=d[u]+1;
if(v==t) return true;
q.push(v);
}
}
}
return false;
}
int dfs(int u,int flow){
if(u==t) return flow;
int left=flow;
for(int i=head[u];i&&left;i=nxt[i]){
int v=ver[i];
if(val[i]&&d[v]==d[u]+1){
int res=dfs(v,min(left,val[i]));
if(!res) d[v]=0;
val[i]-=res;
val[i^1]+=res;
left-=res;
}
}
return flow-left;
}
void tarjan(int u){
dfn[u]=low[u]=++tim;
st[++tp]=u;
for(int i=head[u];i;i=nxt[i]){
int v=ver[i];
if(!val[i]) continue;//注意此处 在残量网络中tarjan
if(!dfn[v]){
tarjan(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_num;
int t;
do{
t=st[tp--];
belong[t]=scc_num;
} while(t!=u);
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1,u,v,w;i<=m;++i){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
while(bfs()) dfs(s,inf);
for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
for(int i=2;i<=Top;i+=2){
int u=ver[i^1],v=ver[i];
if(!val[i]&&belong[u]!=belong[v]) printf("%d ",1);
else printf("%d ",0);
if(!val[i]&&belong[u]==belong[s]&&belong[v]==belong[t]) printf("%d",1);
else printf("%d",0);
putchar('\n');
}
return 0;
}