Uva 10615 Rooks(二分图完美匹配+补边)
来源:互联网 发布:matlab 生成稀疏矩阵 编辑:程序博客网 时间:2024/05/17 02:15
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1556
思路:
1.给棋子染色,要求每行每列棋子颜色均不相同。
2.构造二分图模型,左右各n个点,若第i行第j列存在棋子,则由左边第i个点向右边第j个点连边。则问题变为给边染色,使得每个点所连边颜色均不相同。
3.对于二分图中每个点,若存在一完美匹配,则所有匹配边无冲突,可染同一色,设需要使用ans种颜色,则可求ans次完美匹配。
4.由于每点度数可能不相同,完美匹配不一定存在,若最大匹配不是完美匹配,则有可能造成ans次匹配后存在边为染色,所以应添加多余的边,使得每次求出的匹配为最大匹配。
5.设所有点的最大度数为k,则所需颜色数至少为k。
5.若左边一点的所连边数小于k,则寻找右边所连边数小于k的点,连边,直到左边所有点所连边数等于k。则该二分图为k阶正则二分图(每点的度数均为k),由定理可知k阶正则二分图必存在完美匹配,则找到该组匹配后,从图中删去匹配边,二分图变为k-1阶正则二分图,一直处理,知道所有边都匹配为止。由此,ans=k。补边后求k次完美匹配即可。
#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;const int maxn=100+50;int n,ans;int vis[maxn];char ch[maxn][maxn];vector<int> g[maxn];int ansG[maxn][maxn];int rt[maxn],lt[maxn];int cnt1[maxn],cnt2[maxn];int match(int u){ for(int i=0; i<g[u].size(); i++) { int nt=g[u][i]; if(!vis[nt]) { vis[nt]=1; if(rt[nt]==-1||match(rt[nt])) { rt[nt]=u; lt[u]=nt; return 1; } } } return 0;}void hungary(){ memset(rt,-1,sizeof(rt)); for(int i=1; i<=n; i++) { memset(vis,0,sizeof(vis)); match(i); }}void init(){ ans=0; memset(cnt1,0,sizeof(cnt1)); memset(cnt2,0,sizeof(cnt2)); memset(ansG,0,sizeof(ansG)); for(int i=0; i<=n; i++) g[i].clear();}void solve(){ for(int i=1; i<=ans; i++) { hungary(); for(int j=1; j<=n; j++) { if(ch[j][lt[j]]=='*') { //cout<<j<<" "<<lt[j]<<endl; ansG[j][lt[j]]=i; } for(int k=0; k<g[j].size(); k++) { if(g[j][k]==lt[j]) { // cout<<"* "<<j<<" "<<lt[j]<<" "<<g[j][k]<<endl; g[j].erase(g[j].begin()+k); break; } } } }}void build(){ for(int i=1; i<=n; i++) { ans=max(ans,max(cnt1[i],cnt2[i])); } for(int i=1; i<=n; i++) { for(int j=1; j<=n&&cnt1[i]<ans; j++) { while(cnt1[i]<ans&&cnt2[j]<ans) { cnt1[i]++,cnt2[j]++; g[i].push_back(j); } } }}int main(){#ifdef debu freopen("in.txt","r",stdin);#endif // debug int t; scanf("%d",&t); while(t--) { scanf("%d",&n); init(); for(int i=1; i<=n; i++) { getchar(); for(int j=1; j<=n; j++) { scanf("%c",&ch[i][j]); if(ch[i][j]=='*') { cnt1[i]++,cnt2[j]++; g[i].push_back(j); } } } build(); solve(); printf("%d\n",ans); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if(j==1) printf("%d",ansG[i][j]); else printf(" %d",ansG[i][j]); } printf("\n"); } } return 0;}
阅读全文
0 0
- Uva 10615 Rooks(二分图完美匹配+补边)
- Uva 10615 Rooks(二分图匹配)
- uva 10615 - Rooks(完美匹配)
- [UVA 10615]Rooks[二分图匹配]
- UVA 10615 Rooks <二分图 + 正则二分图 + 完全匹配>
- UVA - 10615 Rooks(二分图匹配 + 枚举)
- (intermediate) 二分图(边着色) UVA 10615 Rooks
- UVa live6525Attacking rooks(二分最大匹配之最大匹配)
- UVA 1411 - Ants(二分图完美匹配)
- UVA 10888 - Warehouse(二分图完美匹配)
- hnu 13028 Attacking rooks(二分图匹配 匈牙利算法)
- uva 12530 Game of Tiles (二分图完美匹配+博弈论)
- uva 11383 Golden Tiger Claw 二分图完美匹配
- Uva 1411 ants(KM算法--二分图最佳完美匹配)
- Uva - 11383 - Golden Tiger Claw(二分图最佳完美匹配)
- UVA 11383 - Golden Tiger Claw(二分图完美匹配扩展)
- UVA 1045 - The Great Wall Game(二分图完美匹配)
- UVA 1349 Optimal Bus Route Design (最小费用流 -- 二分图最小权完美匹配)
- linked-list-cycle-ii Java code
- java与mysql时间类型对应(转载,未验证)
- Ubuntu经验/技巧
- scrapy 知乎模拟登录
- 反射机制reflect
- Uva 10615 Rooks(二分图完美匹配+补边)
- 选择Spring Boot项目的内嵌容器
- C++ 构造函数后面的冒号的作用
- laravel 学习笔记——路由(路由与控制器、资源路由)
- 数据库主从、主主,负载均衡,高可用
- 单例软件设计模式初解
- 深入理解Spring MVC 思想
- BootStrap(一)
- 文字超出隐藏并显示省略号