二分图最大匹配——匈牙利算法
对不起 懒得粘 图太多 但是真的好秀 人家创作的确实好,真丶看一遍就懂了
作者:Dark_Scope
来源:CSDN
原文:https://blog.csdn.net/dark_scope/article/details/8880547
板子错误已经改好了,一个是反向边没建好,一个是重边没去,一个是爆int,0.0
写这个博客 主要还不是不喜欢书上的板子,自己理解后按照自己的理解写出最适合自己的板子多好
留个匈牙利算法的板子
hdu 1068
//#include
#include
#include
#include
#include
using namespace std;
const int N=3e3+7;
vectorson[N];
bool vis[N];
int gx[N],gy[N];
bool dfs(int x)
{
for(int i=0;i
最大流问题就是一张带权有向图,权值代表流量,问起点到终点的最大流
后续会更新啦,目前只是初步学习,就是当个笔记记下来啦
第一份是BFS,就是利用bfs每次找一条最短路,记录路径和路径所有边最小权值,然后所有边都减去该值,直到无通路(其实就是个bfs+记录路径+修改权值)是我太菜了理解了半天,此处留下第一个板子
(这是EK算法)(板子不放了,复杂度不优秀)
还有优化后的dinic算法和弧优化后的。(没有弧优化的没摸出来,摸出来再放,因为学长说网络流的题都是玄学优化的,所以任何一点优化都不要放过的好)
剪枝+弧优化的Dinic算法(终于在同学的帮助下,修好了邻接表,改好了弧优化,改吐了)
#include
using namespace std;
const double pi = acos(-1.0);
typedef long long ll;
const ll N=1e5+7;
const ll inf=1e18;
const ll mod=1e9+7;
struct node
{
int to,rev;
ll w;
};
vectorson[207];
ll dep[207],now[207];
ll n,m,s,t;
void add(int from,int to,ll cap)
{
node temp{to,son[to].size(),cap};
son[from].push_back(temp);
node temp2{from,son[from].size()-1,0};
son[to].push_back(temp2);
}
bool bfs()
{
for(int i=1;i<=n;i++) dep[i]=-1,now[i]=0;
dep[s]=0;
queueq;
q.push(s);
while(q.size())
{
ll x=q.front();
q.pop();
for(ll i=0;i>n>>m>>s>>t;
while(m--)
{
ll a1,a2,a3;
cin>>a1>>a2>>a3;
add(a1,a2,a3);
}
ll ans=0;
while(bfs()) ans+=dfs(s,inf);
cout<
匈牙利算法跑二分图时间复杂度是nm,如果用dinic的话时间是msprt(n)
例题 多校hdu第四场 H go running
题目大意 有n个点表示时间t时x点有人,要用最少的学生覆盖这些点,每个学生只能选一个起点和方向然后以1m/s的时间跑
做一个超级原点和汇点就是二分图求最大流就好
#include
#include
#include
#include
#include
#include
using namespace std;
const double pi = acos(-1.0);
typedef long long ll;
const ll N=1e5+7;
const ll inf=1e18;
const ll mod=1e9+7;
struct node
{
int to,rev;
ll w;
};
struct pppp
{
int t,x;
}a[N];
vectorson[N*2];
ll dep[N*2],now[N*2];
ll n,m,s,t;
void add(int from,int to,ll cap)
{
node temp{to,son[to].size(),cap};
son[from].push_back(temp);
node temp2{from,son[from].size()-1,0};
son[to].push_back(temp2);
}
bool bfs()
{
for(int i=1;i<=n;i++) dep[i]=-1,now[i]=0;
dep[s]=0;
queueq;
q.push(s);
while(q.size())
{
ll x=q.front();
q.pop();
for(ll i=0;i>zs;
while(zs--)
{
int nn;
cin>>nn;
int t1=0,t2=0;
unordered_mapmp1,mp2;
for(int i=1;i<=nn;i++)
{
cin>>a[i].t>>a[i].x;
if(!mp1[a[i].x-a[i].t]) mp1[a[i].x-a[i].t]=++t1;
if(!mp2[a[i].x+a[i].t]) mp2[a[i].x+a[i].t]=++t2;
}
s=t1+t2+1;
t=s+1;
//cout<
最小费用最大流问题
在最大流问题的基础上每条边多了个权值,在完成最大流的基础上使费用最少
跑dijkstra算法每次跑出最短路,然后进行和最大流一样的做法,然后再跑最短路直到跑出最大流
留个板子,下一个是最小割
SPFA+dinic 其实就是把dinic里面的bfs改为spfa 标记进去过的点,和存下最短距离(说的简单,改了半天的板子)
#include
using namespace std;
const double pi = acos(-1.0);
typedef long long ll;
#define FOPEN freopen("C:\\Users\\l\\P3381_8.in","r",stdin)
const ll N=5e3+7;
const ll inf=1e18;
const ll mod=1e9+7;
struct node
{
int to,rev;
ll w,cost;
};
vectorson[N];
ll dep[N],now[N],vis[N];
ll n,m,s,t;
ll maxflow,mincost;
void add(int from,int to,ll w,ll cost)
{
node temp{to,son[to].size(),w,cost};
son[from].push_back(temp);
node temp2{from,son[from].size()-1,0,-cost};
son[to].push_back(temp2);
}
bool bfs()
{
for(int i=1;i<=n;i++) dep[i]=inf,now[i]=0,vis[i]=0;
dep[s]=0;
queueq;
q.push(s);
vis[s]=1;
while(q.size())
{
ll x=q.front();
q.pop();
vis[x]=0;
for(ll i=0;idep[x]+son[x][i].cost&&son[x][i].w)
{
dep[d]=dep[x]+son[x][i].cost;
if(!vis[d])q.push(d),vis[d]=1;
}
}
}
//for(int i=1;i<=n;i++ )cout<>n>>m>>s>>t;
//cout<>a1>>a2>>a3>>a4;
add(a1,a2,a3,a4);
}
while(bfs()) dfs(s,inf);
cout<
EK+Dijkstra(等我摸出来放)
#include
using namespace std;
const double pi = acos(-1.0);
typedef long long ll;
#define FOPEN freopen("C:\\Users\\l\\P3381_8.in","r",stdin)
#define P pair
const ll N=5e3+7;
const ll inf=1e18;
const ll mod=1e9+7;
struct node
{
ll to,rev;
ll w,cost;
};
vectorson[N];
ll dep[N];
ll h[N],pre[N],prei[N];
ll n,m,s,t;
ll maxflow,mincost;
ll f=inf;
void add(ll from,ll to,ll w,ll cost)
{
node temp{to,son[to].size(),w,cost};
son[from].push_back(temp);
node temp2{from,son[from].size()-1,0,-cost};
son[to].push_back(temp2);
}
inline void Dijk()
{
for(int i=1;i<=n;i++) h[i]=0;
while(f)
{
priority_queue,greater
>p;
for(int i=1;i<=n;i++) dep[i]=inf;
dep[s]=0;
p.push(P(0,s));
while(p.size())
{
P x=p.top();
p.pop();
if(x.second==t) break;
if(dep[x.second]dep[d]+dd.cost+h[d]-h[dd.to])
{//cout<>n>>m>>s>>t;
//cout<
上面这个板子的时间复杂度已经很可以了
dijkstra+EK的我也摸出来了 可是时间复杂度很是不理想(emmm)都差不多一样的为什么比别人的慢这么多
#include
using namespace std;
const double pi = acos(-1.0);
typedef long long ll;
#define FOPEN freopen("C:\\Users\\l\\P3381_8.in","r",stdin)
#define P pair
const ll N=5e3+7;
const ll inf=1e18;
const ll mod=1e9+7;
struct node
{
ll to,rev;
ll w,cost;
};
vectorson[N];
ll dep[N];
ll h[N],pre[N],prei[N];
ll n,m,s,t;
ll maxflow,mincost;
ll f=inf;
void add(ll from,ll to,ll w,ll cost)
{
node temp{to,son[to].size(),w,cost};
son[from].push_back(temp);
node temp2{from,son[from].size()-1,0,-cost};
son[to].push_back(temp2);
}
inline void Dijk()
{
while(f)
{
priority_queue,greater
>p;
for(int i=1;i<=n;i++) dep[i]=inf;
dep[s]=0;
p.push(P(0,s));
while(p.size())
{
P x=p.top();
p.pop();
if(x.second==t) break;
if(dep[x.second]dep[d]+dd.cost+h[d]-h[dd.to])
{//cout<>n>>m>>s>>t;
//cout<