标签:bsp names 退出 math 容量 lib span efi using
//dinic 最大流 //head[x]从0开始记 这样便于找反向边 异或即可 //当前弧优化 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #define ll long long #define ull unsigned long long #define INF 0x3f3f3f3f using namespace std; int n,m,s,t,ans,cnt=-1;//s源点,t汇点 int head[10001],cur[10001],dep[10001]; struct uio{ int nxt,to,wei; }edge[200001]; void add(int x,int y,int z) { edge[++cnt].nxt=head[x]; edge[cnt].to=y; edge[cnt].wei=z; head[x]=cnt; } bool bfs()//分层 { memset(dep,0x3f,sizeof(dep)); queue<int> que; while(!que.empty()) que.pop(); memcpy(cur,head,sizeof(head)); dep[s]=0; que.push(s); while(!que.empty()) { int now=que.front(); que.pop(); for(int i=head[now];i!=-1;i=edge[i].nxt) if(dep[edge[i].to]==INF&&edge[i].wei)//还未被分层且为正向边 { dep[edge[i].to]=dep[now]+1; que.push(edge[i].to); } } if(dep[t]<INF)//有增广路 return true; else return false; } int dfs(int now,int lim)//寻找可增加流量 //lim指源点到now的路径最小边权 { if(!lim||now==t)//到这个点没有可增广流量或已到汇点 return lim; int flow=0,change;//flow当前点可增广的流量 change每次增广流量 for(int i=cur[now];i!=-1;i=edge[i].nxt) { cur[now]=i; if(dep[edge[i].to]==dep[now]+1&&(change=dfs(edge[i].to,min(lim,edge[i].wei)))) //如果下一个点可被增广且可增广流量大于0 { flow+=change; lim-=change; edge[i].wei-=change; edge[i^1].wei+=change; if(!lim) break;//没有容量可供增广就退出 } } return flow; } void dinic() { while(bfs())//分层 ans+=dfs(s,INF); } int main() { memset(head,-1,sizeof(head)); scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w);//正向边 add(v,u,0);//反向边 } dinic(); printf("%d\n",ans); return 0; }
标签:bsp names 退出 math 容量 lib span efi using
原文地址:https://www.cnblogs.com/water-radish/p/9280669.html