#define MAXN 1005
#define INF 2000000000
int source,sink; //源点 汇点
struct tree
{
int from,to,flow,worth,next; //结点,流量,费用,链表
tree(){}
tree(int fr,int ro,int fl,int wo,int ne)
{
from=fr,to=ro,flow=fl,worth=wo,next=ne;
}
}e[MAXN*MAXN];
int g[MAXN]; // 建立链表
int num; //边数
void init() //初始化
{
memset(g,0,sizeof(g));
num=1;
}
void addtree(int from,int to,int flow,int worth) //建图
{
e[++num]=tree(from,to,flow,worth,g[from]);
g[from]=num;
e[++num]=tree(to,from,0,-worth,g[to]); //反向弧
g[to]=num;
}
bool visque[MAXN]; //查看是否入队
int dis[MAXN]; //最小距离
int pre[MAXN],prx[MAXN]; //记录路线用于更新残量图
queue<int>q;
int bfs() //寻找最短路
{
while(!q.empty()) q.pop(); //初始化队列
for(int i=0;i<=MAXN;i++) dis[i]=INF; //初始化距离
q.push(source); //源点入队
dis[source]=0;
visque[source]=true;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=g[u];i;i=e[i].next)
{
if(e[i].flow>0&&dis[u]+e[i].worth<dis[e[i].to]) //更新最短路
{
dis[e[i].to]=dis[u]+e[i].worth;
pre[e[i].to]=u;
prx[e[i].to]=i;
if(!visque[e[i].to])
{
visque[e[i].to]=true;
q.push(e[i].to);
}
}
}
visque[u]=false; //前面已经让u出队了所以这里要写一下
}
return dis[sink]!=INF; //判断是否可以到达汇点
}
int dfs()
{
int u=sink;
int ans=INF;
while(u!=source) //找当前路中的最小流量
{
if(e[prx[u]].flow<ans) ans=e[prx[u]].flow;
u=pre[u];
}
u=sink;
while(u!=source) //更新残量图
{
e[prx[u]].flow-=ans;
e[prx[u]^1].flow+=ans;
u=pre[u];
}
return ans*dis[sink];
}
int solve()
{
int cur=0;
int ans=0;
while(bfs())
{
cur+=dfs();
if(cur>ans) ans=cur;
}
return ans;
}
最小费用最大流(模板)
最新推荐文章于 2024-04-23 18:26:20 发布