【题解】[CQOI2008] 传感器网络/二分图匹配最小字典序

我是个调了一下午的蒟蒻

待会来讲一下这个算法的原理。

理论上,这个做法可以处理所有 二分图匹配最小字典序 问题。

#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; const int N=55*55; //判断是否存在匹配包含 (u,v) //看是否存在环 //若存在环,将路径全部取反 //**然后删掉 (u,v) 这条边** //适用于完美匹配 -> 拆点 + 建虚点 int n,match[N],dfn[N],l[N],r[N],cnt,num,in[N],id[N]; char ch[55]; vector<int> g[N],g2[N]; //dfn 标记打在右部节点 bool dfs(int u) { for(auto v:g2[u]) { if(dfn[v]==num) continue; dfn[v]=num; if(match[v]==-1||dfs(match[v])) { match[v]=u; return 1; } } return 0; } int dfs(int u,int topf) { for(auto v:g2[u]) { if(dfn[v]==num) continue; dfn[v]=num; if(match[v]==topf||(match[v]>topf&&dfs(match[v],topf)!=-1)) { match[v]=u; return v; } } return -1; } bool check(int mid) { cnt=0; for(int i=0;i<n;i++) in[i]=mid; in[n]=n; for(int i=0;i<=n;i++) { l[i]=cnt; for(int j=1;j<=in[i];j++) { id[cnt++]=i; } r[i]=cnt; } for(int i=0;i<n;i++) { g2[i].clear(); } for(int i=0;i<n;i++) { for(auto j:g[i]) { for(int k=l[j];k<r[j];k++) { g2[i].push_back(k); } } } memset(match,-1,sizeof match); for(int i=0;i<=n-1;i++) { num++; if(!dfs(i)) return 0; } return 1; } int main() { scanf("%d",&n); scanf("%s",ch); for(int i=0;i<n;i++) { char Ch[55]; scanf("%s",Ch); for(int j=0;j<n;j++) { if(Ch[j]=='Y') { g[i].push_back(j); } } } for(int i=0;i<n;i++) { if(ch[i]=='Y') { g[i].push_back(n); } } int l=0,r=n,res=0; while(l<=r) { int mid=(l+r)/2; if(check(mid)) res=mid,r=mid-1; else l=mid+1; } check(res); for(int i=n;i<cnt;i++) { for(int j=0;j<cnt;j++) { g2[i].push_back(j); } dfs(i); } for(int i=0;i<n;i++) { num++; printf("%d ",id[dfs(i,i)]); } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530171.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(10)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示