P1525 [NOIP2010 提高组] 关押罪犯
思路:
1.怨气值从小到大单调可以二分答案查找最小值
2.判断两人两人构成的路径是否可以构成二分表,若可以则可以作为答案继续向更小的情况查找
3.判断是否可以构成二分表:bfs搜索使用染色法,首先把一个点标记成黑色(1),然后开始bfs,枚举所有与它相连的点,将它们标记成白色(2),不断遍历整张图,如果你发现下一个染色的点已经有了颜色,判断是否与此时你在的点颜色一致。若是颜色一致,说明染色存在冲突,无法拆成二分图
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,sum,maxx,l,r,mid;
int a[100005],c[100005];
struct edge{
int u;
int w;
int v;
}b[200005];
void add(int x,int y,int z){
b[++sum].u=a[x];
b[sum].v=y;
b[sum].w=z;
a[x]=sum;
}
bool bfs(int mid){
memset(c,0,sizeof(c));
queue<int>q;
for(int i=1;i<=n;i++){
if(c[i]) continue;
q.push(i);
c[i]=1;
while(!q.empty()){
int k=q.front();
q.pop();
for(int j=a[k];j;j=b[j].u){
if(b[j].w>=mid){
if(c[b[j].v]==0){
c[b[j].v]=c[k]==1?2:1;
q.push(b[j].v);
}
else if(c[b[j].v]==c[k])
return false;
}
}
}
}
return true;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int aa,bb,cc;
cin>>aa>>bb>>cc;
maxx=max(maxx,cc);
add(aa,bb,cc);
add(bb,aa,cc);
}
l=0;
r=maxx+1;
while(l+1<r){
mid=(l+r)/2;
if(bfs(mid)) r=mid;
else l=mid;
}
cout<<l;
return 0;
}
P3386 【模板】二分图最大匹配
思路:
1.以数组a标记数字所在集合,若两数在同一集合中则数组a中数字一致
2.分z为1和2两种情况判断(小心部分特殊情况)
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,e;
int a[505][505],b[505];
bool f[505];
bool dfs(int u){
for(int v=1;v<=m;v++){
if(a[u][v]&&!f[v]){
f[v]=true;
if(b[v]==-1||dfs(b[v])){
b[v]=u;
return true;
}
}
}
return false;
}
int hungary(){
int s=0;
memset(b,-1,sizeof(b));
for(int i=1;i<=n;i++){
memset(f,false,sizeof(f));
if(dfs(i)) s++;
}
return s;
}
int main(){
cin>>n>>m>>e;
for(int i=1;i<=e;i++){
int u,v;
cin>>u>>v;
a[u][v]=1;
}
cout<<hungary();
return 0;
}
P1129 [ZJOI2007] 矩阵游戏
思路:
1.构建二分图:一边为列数,一边为行数,若第i行第j列是1,就给列数j和行数i连一条路径
2.行和列匹配,但实际上则是路径和路径进行匹配,最后要行列相等的匹配,即最大匹配数等于边数的时候可以交换得到成功匹配,输出yes,否则输出no
代码:
#include<bits/stdc++.h>
using namespace std;
int T,n,s;
int a[505][505],m[505],f[505];
bool dfs(int x){
for(int i=1;i<=n;i++){
if(a[x][i]==1&&f[i]==0){
f[i]=1;
if(m[i]==0||dfs(m[i])){
m[i]=x;
return true;
}
}
}
return false;
}
int main(){
cin>>T;
for(int i=1;i<=T;i++){
memset(a,0,sizeof(a));
memset(m,0,sizeof(m));
s=0;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++){
memset(f,0,sizeof(f));
s+=dfs(i);
}
if(s==n) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}