二分图总结
在二分图中
题目一 染色法
题目链接:https://www.acwing.com/problem/content/259/
思路:二分check 然后判是否能成为二分图, 大于mid 的边可以不用判
1 #include2 using namespace std; 3 const int maxn=1e5+10; 4 const int mod=998244353; 5 #define ll long long 6 #define ull unsigned long long 7 #define pb push_back 8 #define pi pair 9 #define fi first 10 #define sc second 11 12 int n,m; 13 vector E[maxn]; 14 int col[maxn]; 15 int f; 16 17 void dfs(int u,int c,int k) 18 { 19 col[u]=c; 20 for(auto &v:E[u]) 21 { 22 if(v.sc<=k) continue; 23 if(!col[v.fi]) dfs(v.fi,3-c,k); 24 else 25 { 26 if(col[v.fi]==col[u]) f=1; 27 } 28 } 29 } 30 31 int check(int x) 32 { 33 f=0; 34 memset(col,0,sizeof(col)); 35 for(int i=1;i<=n;i++) 36 { 37 if(!col[i]) dfs(i,1,x); 38 } 39 if(f) return 0; 40 else return 1; 41 } 42 43 44 45 int main() 46 { 47 ios::sync_with_stdio(0); 48 cin.tie(0); 49 cin>>n>>m; 50 for(int i=1;i<=m;i++) 51 { 52 int u,v,w; 53 cin>>u>>v>>w; 54 E[u].pb({v,w}); 55 E[v].pb({u,w}); 56 } 57 int l=0,r=1e9; 58 while(l<r) 59 { 60 int mid=(l+r)/2; 61 if(check(mid)) r=mid; 62 else l=mid+1; 63 } 64 cout< '\n'; 65 66 67 68 69 }
题目二 匈牙利算法
题目链接:https://www.acwing.com/problem/content/374/
思路:对于坐标 x y的格子 如果x+y为奇数, 划分为二分图左边,偶数划分为二分图右边
然后每个点可以从上下左右4个方向有一条边,代表一个可以匹配的点,然后二分图匹配即可
这样就可以转换,等价于每条边不能有公共点
1 #include2 using namespace std; 3 const int maxn=1e2+10; 4 const int mod=998244353; 5 #define ll long long 6 #define ull unsigned long long 7 #define pb push_back 8 #define pi pair 9 #define fi first 10 #define sc second 11 12 int n,t; 13 int g[maxn][maxn]; 14 int st[maxn][maxn]; 15 pi match[maxn][maxn]; 16 17 int xx[4]={0,0,1,-1}; 18 int yy[4]={1,-1,0,0}; 19 20 int dfs(int x,int y) 21 { 22 for(int i=0;i<4;i++) 23 { 24 int tx=xx[i]+x; 25 int ty=yy[i]+y; 26 if(tx<1||ty<1||tx>n||ty>n||g[tx][ty]||st[tx][ty]) continue; 27 st[tx][ty]=1; 28 29 int &qx=match[tx][ty].fi,&qy=match[tx][ty].sc; 30 if(!qx||dfs(qx,qy)) 31 { 32 qx=x,qy=y; 33 return 1; 34 } 35 } 36 return 0; 37 } 38 39 int main() 40 { 41 ios::sync_with_stdio(0); 42 cin.tie(0); 43 cin>>n>>t; 44 for(int i=0;i ) 45 { 46 int x,y; 47 cin>>x>>y; 48 g[x][y]=1; 49 } 50 int ans=0; 51 for(int i=1;i<=n;i++) 52 { 53 for(int j=1;j<=n;j++) 54 { 55 if((i+j)%2&&!g[i][j]) 56 { 57 memset(st,0,sizeof(st)); 58 if(dfs(i,j)) ans++; 59 } 60 } 61 } 62 cout< '\n'; 63 64 65 66 67 68 }
题目三 最小点覆盖
题目链接:https://www.acwing.com/problem/content/378/
思路: a[i] 可以连去b[i] 一条有向边, 然后要每个任务都完成,相当于最小点覆盖
注意的是 初始模式是0 所以带0的边可以忽略掉
1 #include2 using namespace std; 3 const int maxn=1e2+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define pi pair 7 #define fi first 8 #define sc second 9 #define pb push_back 10 11 vector<int>E[maxn]; 12 int match[maxn],st[maxn]; 13 int n,m,k; 14 15 16 int dfs(int u) 17 { 18 for(auto &v:E[u]) 19 { 20 if(st[v]) continue; 21 st[v]=1; 22 if(!match[v]||dfs(match[v])) 23 { 24 match[v]=u; 25 return 1; 26 } 27 } 28 return 0; 29 } 30 31 32 33 int main() 34 { 35 ios::sync_with_stdio(0); 36 cin.tie(0); 37 while(cin>>n,n) 38 { 39 cin>>m>>k; 40 for(int i=0;i<=n;i++) E[i].clear(); 41 memset(match,0,sizeof(match)); 42 for(int i=0;i ) 43 { 44 int x,y,z; 45 cin>>x>>y>>z; 46 if(!y||!z) continue; 47 E[y].pb(z); 48 } 49 int ans=0; 50 for(int i=1;i ) 51 { 52 memset(st,0,sizeof(st)); 53 if(dfs(i)) ans++; 54 } 55 cout< '\n'; 56 } 57 58 59 60 61 62 }
题目四 最大独立集
题目链接:https://www.acwing.com/problem/content/description/380/
思路:根据格子的下标之和奇偶来划分,每次跳增加的坐标和为3即奇数
所以每次跳跃都会改变奇偶性,所以我们把坐标和奇偶性不同的格子连一条边
然后就成了一张二分图,然后用最大独立集结论 ans= n*m-t-res
1 #include2 using namespace std; 3 const int maxn=1e2+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define pi pair 7 #define fi first 8 #define sc second 9 #define pb push_back 10 11 int n,m,t; 12 int g[maxn][maxn]; 13 pi match[maxn][maxn]; 14 int st[maxn][maxn]; 15 16 int xx[8]={-1,-2,-2,-1,1,2,2,1}; 17 int yy[8]={-2,-1,1,2,-2,-1,1,2}; 18 19 20 int dfs(int x,int y) 21 { 22 for(int i=0;i<8;i++) 23 { 24 int tx=xx[i]+x; 25 int ty=yy[i]+y; 26 if(tx<1||tx>n||ty<1||ty>m||g[tx][ty]||st[tx][ty]) continue; 27 st[tx][ty]=1; 28 pi tmp=match[tx][ty]; 29 if(!tmp.fi||dfs(tmp.fi,tmp.sc)) 30 { 31 match[tx][ty]={x,y}; 32 return 1; 33 } 34 } 35 return 0; 36 } 37 38 39 40 41 int main() 42 { 43 ios::sync_with_stdio(0); 44 cin.tie(0); 45 cin>>n>>m>>t; 46 for(int i=1;i<=t;i++) 47 { 48 int x,y; 49 cin>>x>>y; 50 g[x][y]=1; 51 } 52 int ans=0; 53 for(int i=1;i<=n;i++) 54 { 55 for(int j=1;j<=m;j++) 56 { 57 if((i+j)%2&&!g[i][j]) 58 { 59 memset(st,0,sizeof(st)); 60 if(dfs(i,j)) ans++; 61 } 62 } 63 } 64 cout< '\n'; 65 66 67 68 69 }