网络流=。=牛逼的东西
dinic
int bfs(){
memset(d,0,sizeof d);
q.push(s);d[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=first[u];i;i=e[i].next){
int v=e[i].v;
if(e[i].cap>e[i].flow&&!d[v]){
d[v]=d[u]+1;q.push(v);
}
}
}return d[t];
}
int dfs(int x,int a){
if(x==t||a==0) return a;
int tmp,f=0;
for(int i=first[x];i;i=e[i].next){
int v=e[i].v;
if(d[v]==d[x]+1&&(tmp=dfs(v,min(a,e[i].cap-e[i].flow)))){
a-=tmp;f+=tmp;
e[i].flow+=tmp;e[i^1].flow-=tmp;
if(!a) break;
}
}
if(!f) d[x]=-1;
return f;
}
void Max_Flow(){
int k=0;
while(bfs()) {Maxflow+=dfs(s,inf);}
}
最小费用最大流
bool spfa(){
memset(d,0x3f,sizeof d);
q.push(s);inq[s]=1;d[s]=0;a[s]=inf;
while(!q.empty()){
int u=q.front();q.pop();inq[u]=false;
for(int i=first[u];i;i=e[i].next){
int v=e[i].v;
if(e[i].cap-e[i].flow>0&&d[v]>d[u]+e[i].cost){
d[v]=d[u]+e[i].cost;a[v]=min(a[u],e[i].cap-e[i].flow);
pre[v]=i;if(!inq[v]){q.push(v);inq[v]=true;}
}
}
}if(d[t]==d[n+2]) return false;
Mincost+=d[t]*a[t];int cur=t;
while(cur!=s){
e[pre[cur]].flow+=a[t];
e[pre[cur]^1].flow-=a[t];
cur=e[pre[cur]].u;
}return true;
}
void Min_cost(){
while(spfa());
}
1. 最大流=最小割
割:删去之后使网络中源点 S 到汇点 T 不存在路径的边的
集合被称为这个网络的一个割。一个割的权值等于删去边的容量
和。
2.求一组最小割
求出最大流后,从源点开始沿残量网络 BFS,标记能够到
达的点。连接已标记的点和未标记的点的正向边就是该网络的一
个最小割集
3.点联通度 拆点连容量 1 原边(u,v) 连两条+∞的边 枚举源点汇点,跑最大流即可
4.边连通度 直接建图 任意源点 枚举汇点即可 /Stoer-Wanger算法(不会)
5.可行边/必须边
6.最大权闭合子图
Orz Zrt 大部分抄自zrt