ネットワークフロー-EKアルゴリズム
EKアルゴリズムの構想:貪欲な思想に基づいて、毎回1本の起点から終点までの経路を選択して、言うまでもなく、この路の流量はこの経路の重み値が最小値であることに等しい.この道の重み値を流量を減らし、経路の反対側に流量を加え(欲張りに後悔する機会を与えることができる)、以上のステップを無限にループして、起点から終点までの道が見つからず、最後にすべての最小値を合わせると最大流になります.コード:
#include
#include
#include
#include
#define LL long long
#define Max 100005
const LL mod=1e9+7;
const LL LL_MAX=9223372036854775807;
using namespace std;
struct node
{
int v,next;
LL w;
}edge[Max];//
int n,m;
int pre[Max],head[Max],rec[Max];//pre ,rec ,head
LL flow[Max];//
int no;
queueq;
void init()
{
no=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,LL c){
edge[no].v=v,edge[no].w=c;
edge[no].next=head[u],head[u]=no++;
edge[no].v=u;edge[no].w=0;
edge[no].next=head[v],head[v]=no++;
}
LL bfs(int st,int en)// st-->en
{
memset(pre,-1,sizeof(pre));
while(!q.empty())q.pop();
pre[st]=st,flow[st]=INT_MAX;
q.push(st);
while(!q.empty()){
int top=q.front();
q.pop();
int now=head[top];
while(now!=-1){
int t=edge[now].v;
if(pre[t]==-1 && edge[now].w>0){// , 0
flow[t]=min(flow[top],edge[now].w);
pre[t]=top;
rec[t]=now;
q.push(t);
}
now=edge[now].next;
}
if(pre[en]!=-1)
return flow[en];
}
return -1;
}
LL EK(int st,int en)
{
LL ans=0;
LL add;
while((add=bfs(st,en))!=-1){// st-->en
ans+=add;
int k=en;
// printf("%d
",add);
while(k!=pre[k]){
edge[rec[k]].w-=add;//
edge[rec[k]^1].w+=add;//
// printf("%d
",k);
k=pre[k];
}
}
return ans;
}
int main()
{
int x,y;
LL c;
while(scanf("%d%d",&m,&n)==2){
init();
for(int i=0;i