图论模板集合
二分图模板
匈牙利算法 时间复杂度O(n^3)
int n1,n2,k; //n1,n2为二分图的顶点集,其中x∈n1,y∈n2 int map[N][N],vis[N],link[N]; //link记录n2中的点y在n1中所匹配的x点的编号 int find(int x) { int i; for(i=1;i<=n2;i++) { if(map[x][i]&&!vis[i])//x->i有边,且节点i未被搜索 { vis[i]=1;//标记节点已被搜索 //如果i不属于前一个匹配M或被i匹配到的节点可以寻找到增广路 if(link[i]==0||find(link[i])) { link[i]=x;//更新 return 1;//匹配成功 } } } return 0; }
Hopcroft-Karp算法 时间复杂度O(n^0.5*e)
vector<int>ed[N]; int xlink[N],ylink[N];/*xlink[i]表示左集合顶点所匹配的右集合顶点序号,ylink[i]表示右集合i顶点匹配到的左集合顶点序号。*/ bool vis[N]; //寻找增广路的标记数组 int dx[N],dy[N];/*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号*/
int dis,n;
void init() { memset(xlink,-1,sizeof(xlink)); memset(ylink,-1,sizeof(ylink)); } int bfs() { memset(dx,-1,sizeof(dx)); memset(dy,-1,sizeof(dy)); int i; queue<int>q; dis = INF; for(i = 1 ; i <= n;i++) if(xlink[i]==-1) { q.push(i); dx[i] = 0; } while(!q.empty()) { int u = q.front(); q.pop(); if(dx[u]>dis) break; for(i = 0 ;i < ed[u].size() ; i++) { int v = ed[u][i]; if(dy[v]==-1) { dy[v] = dx[u]+1; if(ylink[v]==-1) dis = dy[v]; else { dx[ylink[v]] = dy[v]+1; q.push(ylink[v]); } } } } return dis!=INF; } int find(int u) { int i; for(i = 0;i < ed[u].size() ; i++) { int v = ed[u][i]; if(vis[v]||dy[v]!=dx[u]+1) continue; vis[v] = 1; if(ylink[v] != -1&&dy[v]==dis) continue; if(ylink[v]==-1||find(ylink[v])) { ylink[v] = u; xlink[u] = v; return 1; } } return 0; } int hk() { int ans = 0,i; while(bfs()) { memset(vis,0,sizeof(vis)); for(i = 1 ; i <= n ;i++) { if(xlink[i]==-1) ans+=find(i); } } return ans; }
最大流模板
Edmonds-Karp算法 时间复杂度O(n*e^2)
int path[N],flow[N],gh[N][N],st,en; int bfs() { int i; memset(path,-1,sizeof(path)); for(i = 1 ; i <= en ; i++) flow[i] = INF; queue<int>q; q.push(1); while(!q.empty()) { int tk = q.front(); q.pop(); if(tk==en) break; for(i = 1 ; i <= en ; i++) { if(path[i]==-1&&gh[tk][i]) { path[i] = tk; flow[i] = min(flow[tk],gh[tk][i]); q.push(i); } } } if(path[en]==-1) return -1; return flow[en]; } int km() { int now,pre,sum=0,k; while((k=bfs())!=-1) { sum+=k; now = en; while(now!=st) { pre = path[now]; gh[pre][now]-=k; gh[now][pre]+=k; now = pre; } } return sum; }
dinic算法 O(n*n*m)
效率相对于上面快了很多
#define INF 0x3f3f3f const int N = 415; #define M 160015 struct node { int u,v,next; int w; } edge[M<<1]; int head[N],t,vis[N],pp[N],dis[N]; int o[N]; int st,en; int x[N][N],f[N]; void init() { t=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[t].u = u; edge[t].v = v; edge[t].w = w; edge[t].next = head[u]; head[u] = t++; edge[t].u = v; edge[t].v = u; edge[t].w = 0; edge[t].next = head[v]; head[v] = t++; } int bfs() { int i,u; int w; memset(dis,-1,sizeof(dis)); queue<int>q; q.push(st); dis[st] = 0; while(!q.empty()) { u = q.front(); q.pop(); for(i = head[u] ; i != -1 ; i = edge[i].next) { int v = edge[i].v; w = edge[i].w; if(dis[v]<0&&w>0) { dis[v] = dis[u]+1; q.push(v); } } } if(dis[en]>0) return 1; return 0; } int dfs(int u,int te) { int i; int s; if(u==en) return te; for(i = head[u] ; i != -1 ; i = edge[i].next) { int v = edge[i].v; int w = edge[i].w; if(w>0&&dis[v]==dis[u]+1&&(s=dfs(v,min(te,w)))) { edge[i].w-=s; edge[i^1].w+=s; return s; } } dis[u] = -1; return 0; } int dinic() { int flow = 0; int res; while(bfs()) { while(res = dfs(st,INF)) flow+=res; } return flow; }