Bipartite Graph and Network Flow

Keywords: REST network

Two partite graph

  • If an undirected graph's n n n (n < 2)(n < 2)(n < 2)(n < 2)(n < 2) nodes can be divided into two non-empty sets A,BA,BA,B, where A BA bigcap BA B is empty and there are no edges connected between points in the same set, then the undirected graph is called a bipartite graph. A, BA, BA and B are called left and right parts of a bipartite graph, respectively.

Decision of Bipartite Graph

  • Undirected graphs are singular rings in bipartite graphs (rings with odd length)
  • Using dyeing method, one vertex is painted black and the other vertex is painted white. If the color does not match, it is not a bipartite graph, otherwise it is.
bool dfs_(int u,int color) {
   c[u]=color;
   for(int i=head[u];~i;i=e[i].nxt) {
   	int v=e[i].v;
   	if(c[v]&&c[v]==color) return false;
   	if(!c[v]&&!dfs_(v,3-color)) return false;
   } 
   return true;
}

inline pd_() {
   memset(c,0,sizeof(c));
   for(int i=1;i<=n;++i) {
   	if(!c[i]&&!dfs_(i,1))  return false;
   }
   return true;
}

Imprisoned criminals

  • According to the principle that the enemy of the enemy is a friend, it is realized by using and collecting data.
#include <bits/stdc++.h>
using namespace std;
#define maxn 20010
#define maxm 100010

int n,m,f[maxn<<1];
struct node {
   int x,y,z;
}e[maxm];

inline bool cmp_(node aa,node bb) {
   return aa.z > bb.z;
}

int find_(int x) {
   if(f[x]==x) return x;
   return f[x]=find_(f[x]);
}

void readda_() {
   n=read_();m=read_();
   for(int i=1;i<=m;++i) {
   	e[i].x=read_();e[i].y=read_();e[i].z=read_();
   }sort(e+1,e+m+1,cmp_);
   for(int i=0;i<=(n<<1);++i) f[i]=i;
   for(int i=1;i<=m;++i) {
   	int x=find_(e[i].x),y=find_(e[i].y);
   	if(x==y) {printf("%d",e[i].z);return;}
   	int xx=find_(e[i].x+n),yy=find_(e[i].y+n);
   	f[x]=yy;f[y]=xx;
   }
   printf("0");
}
  • It can also be judged by dichotomy +++ dichotomy.
  • Minimum dichotomy, connect two people whose anger is greater than midmidmid to see if they can be separated, that is, whether they can form a dichotomy.
#include <bits/stdc++.h>
using namespace std;
#define maxn 20010
#define maxm 100010

int n,m,size=0,head[maxn],vis[maxn];
struct node {
	int x,y,z;
}AKIOI[maxm];
struct edge {
	int v,nxt;
}e[maxm<<1];

inline bool cmp_(node aa,node bb) {
	return aa.z > bb.z;
}

inline void add_(int u,int v) {
	e[++size].v=v;
	e[size].nxt=head[u];
	head[u]=size;
}

bool dfs_(int u,int color) {
	vis[u]=color;
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(vis[v]==color) return false;
		if(vis[v]==-1&&!dfs_(v,color^1)) return false;
	}
	return true;
}

inline bool pd_(int now) {
	memset(head,-1,sizeof(head));
	size=0;
	for(int i=1;i<=m;++i) {
		if(AKIOI[i].z<=now) break;
		add_(AKIOI[i].x,AKIOI[i].y);
		add_(AKIOI[i].y,AKIOI[i].x);
	}
	memset(vis,-1,sizeof(vis));
	for(int i=1;i<=n;++i) {
		if(vis[i]==-1&&!dfs_(i,1)) return false;
	}
	return true;
}

void readda_() {
	n=read_();m=read_();
	for(int i=1;i<=m;++i) {
		AKIOI[i].x=read_();AKIOI[i].y=read_();AKIOI[i].z=read_();
	}sort(AKIOI+1,AKIOI+1+m,cmp_);
	int l=0,r=AKIOI[1].z,mid;
	while(l<=r) {
		mid=(l+r)>>1;
		if(pd_(mid)) r=mid-1;
		else l=mid+1;
	}
	printf("%d",l);
}

Maximum matching of bipartite graph

Matching Definition of Graph

  • The set of edges without common endpoints on both edges is called a set of matches of graphs.
  • That is, each point has only one side.

Maximum Matching of Bipartite Graphs

  • In a bipartite graph, a set of matches with the largest number of edges is called the maximum matching of a bipartite graph.

Other relevant definitions

  • For any set of matched SSS (edge set), the edges that belong to SSS are called matched edges, and those that do not belong to SSS are called unmatched edges.
  • The endpoints of the matching edge are called matching points, and the other nodes are called non-matching points.
  • If there is a path path path path connecting two non-matching points in the bipartite graph, so that the non-matching edge and the matching edge appear alternately on the path path path, then the path path path is an augmented path (also called staggered path) of matching SSS.

The nature of augmented road:

  • Length is odd
  • The odd edge is a non-matching edge and the even edge is a matching edge.
  • If the state of all edges on the path (whether they are matched edges or not) is reversed, the new edge set SSS is still a set of matches, and the number of matched edges is increased by 111.

conclusion

  • A set of matching SSS of bipartite graphs is the augmented path of the maximum matching graph without SSS.

Hungarian algorithm (augmented path algorithm)

Main process

  • Let SSS be an empty set, that is, all edges are mismatched edges.
  • Find an augmented path path path, reverse the matching state of all edges on the path path path, and get a larger matching SSS.
  • Repeat the previous step until there is no augmented path in the graph.

Looking for the Way of Enlargement

  • In turn, try to find a matching right node yyy for each left node xxx.
  • yyy and xxx matching need to satisfy one of the following two parts:
    yyy is a mismatch point
    Y Y Y already matches x'x'x', but if another y'y'y'matches from x'x'x', yyy can match xxx.

Time complexity

  • O(n∗m)O(n*m)O(n∗m)

Maximum Matching of Bipartite Graphs

  • The resetresetreset function of BitSet BitSet is fully assigned to 000.
#include <bits/stdc++.h>
using namespace std;
#define maxn 1010
#define maxm 1000010

int n,m,T,head[maxn<<1],size=0,f[maxn<<1];
struct edge {
	int v,nxt;
}e[maxm<<1];
bitset<(maxn<<1)>vis;

inline void add_(int u,int v) {
	e[++size].v=v;
	e[size].nxt=head[u];
	head[u]=size;
}

bool dfs_(int u) {
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(vis[v]) continue;
		vis[v]=1;
		if(!f[v]||dfs_(f[v])) {
			f[v]=u;
			return 1;
		}
	}
	return 0;
}

void readda_() {
	n=read_();m=read_();T=read_();
	memset(head,-1,sizeof(head));
	while(T--) {
		int x=read_(),y=read_();
		if(x>n||y>m) continue;
		add_(x,y+n);add_(y+n,x);
	}int ans=0;
	for(int i=1;i<=n;++i) {
		vis.reset();
		ans+=dfs_(i);
	}
	printf("%d",ans);
}

Pilot Matching Scheme

  • Give out which bbb pilots aaa pilots can pair with to maximize the number of pair logarithms and the maximum matching problem
  • Just record the matching plan by the way.
#include <bits/stdc++.h>
using namespace std;
#define maxn 220
#define maxm 10010

int n,m,size=0,head[maxn],f[maxn];
struct edge {
	int v,nxt;
}e[maxm];
bool vis[maxn];

inline void add_(int u,int v) {
	e[++size].v=v;
	e[size].nxt=head[u];
	head[u]=size;
}

int dfs_(int u) {
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(vis[v]) continue;
		vis[v]=1;
		if(!f[v]||dfs_(f[v])) {
			f[v]=u;
			return 1;
		}
	}
	return 0;
}

void readda_() {
	m=read_();n=read_();
	int x,y;
	memset(head,-1,sizeof(head));
	while(1) {
		x=read_();y=read_();
		if(x==-1&&y==-1) break;
		add_(x,y);
	}int ans=0;
	for(int i=1;i<=m;++i) {
		memset(vis,0,sizeof(vis));
		ans+=dfs_(i);
	}
	printf("%d\n",ans);
	for(int i=m+1;i<=m+1+n;++i) {
		if(!f[i]) continue;
		printf("%d %d\n",f[i],i);
	}
}

King of the hotel

  • Give nnn individuals, give everyone's favorite room and food, only one person to live in the favorite room, eat the favorite food to meet, for the most satisfying person?
  • Unlike in the past, this problem is one quantity to match two quantities.
  • Can let a person match with the room first, and then with food, if both match, ans++ans++ans + +
  • If neither match, the next person
  • If only one of them can be matched, then this person can not be satisfied, but pay attention to restore fff array!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include <bits/stdc++.h>
using namespace std;
#define maxn 220
#define maxm 10010

int AKIOI,AKNOI,n,m,p,f_1[maxn],f_2[maxn],head_1[maxn],head_2[maxn],size_1=0,size_2=0;
struct edge {
	int v,nxt;
}e_1[maxm],e_2[maxm];
bool vis_1[maxn],vis_2[maxn];

inline void add_1(int u,int v) {
	e_1[++size_1].v=v;
	e_1[size_1].nxt=head_1[u];
	head_1[u]=size_1;
}

inline void add_2(int u,int v) {
	e_2[++size_2].v=v;
	e_2[size_2].nxt=head_2[u];
	head_2[u]=size_2;
}

int dfs_1(int u) {
	for(int i=head_1[u];~i;i=e_1[i].nxt) {
		int v=e_1[i].v;
		if(vis_1[v]) continue;
		vis_1[v]=1;
		if(!f_1[v]||dfs_1(f_1[v])) {
			f_1[v]=u;
			if(AKNOI==u) AKIOI=v;
			return 1;
		}
	}
	return 0;
}

int dfs_2(int u) {
	for(int i=head_2[u];~i;i=e_2[i].nxt) {
		int v=e_2[i].v;
		if(vis_2[v]) continue;
		vis_2[v]=1;
		if(!f_2[v]||dfs_2(f_2[v])) {
			f_2[v]=u;
			return 1;
		}
	}
	return 0;
}

void readda_() {
	n=read_();m=read_();p=read_();
	memset(head_1,-1,sizeof(head_1));
	memset(head_2,-1,sizeof(head_2));
	//Room
	int x; 
	for(int i=1;i<=n;++i) {
		for(int j=1;j<=m;++j) {
			x=read_();
			if(x) add_1(i,j+n);
		}	
	}
	//food 
	for(int i=1;i<=n;++i) {
		for(int j=1;j<=p;++j) {
			x=read_();
			if(x) add_2(i,j+n);
		}
	}
	//matching
	int ans=0;
	for(int i=1;i<=n;++i) {
		memset(vis_1,0,sizeof(vis_1));
		AKNOI=i;		
		int pdc=dfs_1(i);
		if(!pdc) continue;
		memset(vis_2,0,sizeof(vis_2));
		pdc+=dfs_2(i);
		if(pdc==2) ++ans;
		else if(pdc==1) f_1[AKIOI]=0;//reduction
	}
	printf("%d",ans);
}

Chessboard coverage

  • Give the size of the chessboard n nn nn n, and then give mmm forbidden grid points. Ask how many pieces of length 222 and width 111 dominoes can be put in the case of no overlap?
  • Data range of this question does not allow the use of pressure DP

Two Elements of Bipartite Graph Matching Model

  • Nodes can be divided into two sets, each with 1000 edges. Element 000 for short
  • Each node can only be connected to 111 matching edges. Element 111 for short.

Two Elements Embodied in the Topic

  • 111 Elements: Each lattice can only be covered by one domino, and one domino can cover 222 adjacent lattices.
    Places on the chessboard that are not forbidden are used as nodes and dominoes as edges.

  • 000 Elements: Dye the chessboard black and white, the same color of the lattice can not be covered by the same domino.
    Consider the white grid as the left node and the black grid as the right node for maximum matching.

  • Time complexity O(n2m2)O(n^{2}m^{2})O(n2m2)

#include <bits/stdc++.h>
using namespace std;
#define maxn 110
#define maxm maxn*maxn*8

int n,m,size=0,head[maxn*maxn],f[maxn*maxn];
int dx[]={1,-1,0,0};int dy[]={0,0,1,-1};
bool vis[maxn*maxn],a[maxn][maxn];
struct edge {
	int v,nxt;
}e[maxm];

inline void add_(int u,int v) {
	e[++size].v=v;
	e[size].nxt=head[u];
	head[u]=size;
}

int dfs_(int u) {
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(vis[v]) continue;
		vis[v]=1;
		if(f[v]==-1||dfs_(f[v])) {
			f[v]=u;
			return 1;
		}
 	}
	return 0;
}

void readda_() {
	n=read_();m=read_();
	while(m--) {
		int x=read_(),y=read_();
		a[x-1][y-1]=1;
	}memset(head,-1,sizeof(head));
	for(int i=0;i<n;++i) {
		for(int j=0;j<n;++j) {
			if(a[i][j]) continue;
			for(int k=0;k<4;++k) {
				int px=i+dx[k];
				int py=j+dy[k];
				if(px<0||py<0||px>=n||py>=n) continue;
				if(a[px][py]) continue;//bug
				add_(i*n+j,px*n+py);
				add_(px*n+py,i*n+j);
			}
		}
	}int ans=0;
	memset(f,-1,sizeof(f));
	for(int i=0;i<n;++i) {
		for(int j=0;j<n;++j) {
			if((i^j)&1) continue;
			memset(vis,0,sizeof(vis));
			ans+=dfs_(i*n+j);
		}
	}
	printf("%d",ans);
}

Vehicle placement

  • Give the chessboard size n mn*mn m, give ttt forbidden points, a car can attack the same row or the same train, ask how many cars can not attack each other at most?

  • Element 111: 111 cars per row, no columns
    Use rows and columns as nodes. If the lattice is not prohibited, then the rows and columns of the lattice are connected.

  • 000 Elements: There are no boundaries between rows, and no boundaries between columns

  • The graph above is a bipartite graph, with row nodes as left nodes and column nodes as right nodes to find the maximum matching.

  • Time complexity: O ((n + m) nm), O((n+m)nm)O((n+m)nm)O((n+m)nm)

#include <bits/stdc++.h>
using namespace std;
#define maxn 210

int n,m,T,size=0,head[maxn+maxn],f[maxn+maxn];
bool a[maxn][maxn],vis[maxn+maxn];
struct edge {
	int v,nxt;
}e[maxn*maxn];

inline void add_(int u,int v) {
	e[++size].v=v;
	e[size].nxt=head[u];
	head[u]=size;
}

int dfs_(int u) {
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(vis[v]) continue;
		vis[v]=1;
		if(!f[v]||dfs_(f[v])) {
			f[v]=u;
			return 1;
		}
	}
	return 0;
} 

void readda_() {
	n=read_();m=read_();T=read_();
	while(T--) {
		int x=read_(),y=read_();
		a[x][y]=1;
	}memset(head,-1,sizeof(head));
	for(int i=1;i<=n;++i) {
		for(int j=1;j<=m;++j) {
			if(a[i][j]) continue;	
			add_(i,j+n);
		} 
	}int ans=0;
	for(int i=1;i<=n;++i) {
		memset(vis,0,sizeof(vis));
		ans+=dfs_(i);
	}
	printf("%d",ans);
}

[ZJOI2007] Matrix Game

  • Given a 010101 matrix, two rows or two columns of color can be exchanged. Can we finally make the diagonal line from the upper left corner to the lower right corner 111?
  • Our target state is a [i] [i] = 1a[i][i]=1a[i][i]=1a[i][i]=1
  • If a[i][j] is 1a[i][j] is 1a[i][j] is 1a[i][j], then III and jjj are connected. We find that if we exchange rows or columns, the original graph remains unchanged, that is, as long as there is a column 111 in iii, 111 can be constructed. If all III have corresponding jj, the condition is satisfied.
  • Hungarian algorithm is used to find the maximum matching to see whether the maximum matching is nnn or not.
#include <bits/stdc++.h>
using namespace std;
#define maxn 210

int T,n,head[maxn<<1],f[maxn<<1],size=0;
bool vis[maxn<<1];
struct edge {
	int v,nxt;
}e[maxn*maxn];

inline void add_(int u,int v) {
	e[++size].v=v;
	e[size].nxt=head[u];
	head[u]=size; 
}

int dfs_(int u) {
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(vis[v]) continue;
		vis[v]=1;
		if(!f[v]||dfs_(f[v])) {
			f[v]=u;
			return 1;
		}
	}
	return 0;
}

void readda_() {
	T=read_();
	while(T--) {
		n=read_();size=0;
		memset(head,-1,sizeof(head));
		memset(f,0,sizeof(f));
		for(int i=1;i<=n;++i) {
			for(int j=1;j<=n;++j) {
				int x=read_();
				if(x) add_(i,j+n);
			} 
		}int ans=0;
		for(int i=1;i<=n;++i) {
			memset(vis,0,sizeof(vis));
			ans+=dfs_(i);
		}
		if(ans==n) printf("Yes\n");
		else printf("No\n");
	}
}

Superhero [HNOI2006]

  • Give nnn questions, mmm solutions, iii solutions for each question. One solution can only be used once. How many questions can you answer at most? Note: This is a pass-through game, that is, if this problem can not be solved, the next question can not be answered. The game is over.
  • Bipartite graph maximum matching template questions, attention can not be answered on the end.
#include <bits/stdc++.h>
using namespace std;
#define maxn 2050
#define maxm 1010

int n,m,head[maxn],f[maxn],ans[maxn],size=0;
bool vis[maxn];
struct edge {
	int v,nxt;
}e[maxm<<1];

inline void add_(int u,int v) {
	e[++size].v=v;
	e[size].nxt=head[u];
	head[u]=size;
}

bool dfs_(int u) {
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(vis[v]) continue;
		vis[v]=true;
		if(!f[v]||dfs_(f[v])) {
			f[v]=u;ans[u]=v;
			return 1;
		}
	}
	return 0;
}

void readda_() {
	n=read_();m=read_();
	memset(head,-1,sizeof(head));
	for(int i=1;i<=m;++i) {
		int x=read_(),y=read_();
		add_(i,x+m+1);add_(i,y+m+1);
	}int AKIOI=0;
	for(int i=1;i<=m;++i) {
		memset(vis,0,sizeof(vis));
		if(dfs_(i)) ++AKIOI;
		else break;
	}
	printf("%d\n",AKIOI);
	for(int i=1;i<=AKIOI;++i) {
		printf("%d\n",ans[i]-m-1); 
	}
}

Seating arrangement

  • There are nnn people. Each person has two rows of seats he likes. Each row has two seats. Ask how many people can sit in his favorite seat at most.
  • Take each row as a disassembly point and split it into two points. Note that the array should be large enough.
#include <bits/stdc++.h>
using namespace std;
#define maxn 12010
#define maxm 4010

int n,head[maxn],m,size=0,f[maxn];
bool vis[maxn];
struct edge {
	int v,nxt;
}e[maxm<<2];

inline void add_(int u,int v) {
	e[++size].v=v;
	e[size].nxt=head[u];
	head[u]=size;
}

bool dfs_(int u) {
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(vis[v]) continue;
		vis[v]=1;
		if(!f[v]||dfs_(f[v])) {
			f[v]=u;
			return true;
		}
	}
	return false;
}

void readda_() {
	n=read_();m=n<<1;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=m;++i) {
		int x=read_(),y=read_();
		add_(i,x+m);add_(i,y+m);
		add_(i,x+m+m);add_(i,y+m+m);
	}int ans=0;
	for(int i=1;i<=m;++i) {
		memset(vis,0,sizeof(vis));
		if(dfs_(i)) ++ans;
	}
	printf("%d",ans);
}

Network flow

Maximum flow

[Template] Maximum Network Flow

  • Judge restrestrest as positive or not in the loop section
#include <bits/stdc++.h>
using namespace std;
#define maxn 10050
#define maxm 100050
#define INF 1000000007

int n,m,s,t,head[maxn],cur[maxn],d[maxn],sze=1;
struct edge {
   int v,w,nxt;
}e[maxm<<1];

inline void add_(int u,int v,int w) {
   e[++sze].v=v;
   e[sze].w=w;
   e[sze].nxt=head[u];
   head[u]=sze;
}

inline bool bfs_() {
   memset(d,0,sizeof(d));
   d[s]=1;queue<int>q;
   q.push(s);
   while(!q.empty()) {
   	int u=q.front();q.pop();
   	for(int i=head[u];~i;i=e[i].nxt) {
   		int v=e[i].v;
   		if(e[i].w&&!d[v]) {
   			d[v]=d[u]+1;
   			q.push(v);
   			if(v==t) return true ;
   		}
   	}
   }
   return false ;
}

int dinic_(int u,int flow) {
   if(u==t||!flow) return flow;
   int rest=flow;
   for(int &i=cur[u];~i;i=e[i].nxt) {
   	int v=e[i].v;
   	if(e[i].w&&d[v]==d[u]+1) {
   		int k=dinic_(v,min(rest,e[i].w));
   		if(!k) d[v]=0;
   		e[i].w-=k;
   		e[i^1].w+=k;
   		rest-=k;
   		if(!rest) break;
   	}
   }
   return flow-rest ;
}

void readda_() {
   n=read_();m=read_();
   s=read_();t=read_();
   memset(head,-1,sizeof(head));
   int x,y,z;
   for(int i=1;i<=m;++i) {
   	x=read_(),y=read_(),z=read_();
   	add_(x,y,z);add_(y,x,0);
   }int ans=0;
   while(bfs_()) {
   	for(int i=1;i<=n;++i) cur[i]=head[i];
   	ans+=dinic_(s,INF);
   }
   printf("%d",ans);
}

Posted by scm24 on Sun, 22 Sep 2019 04:16:41 -0700