您的位置:首页 > 其它

UVA 10615 Rooks <二分图 + 正则二分图 + 完全匹配>

2016-07-22 21:32 435 查看
题目:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=11&page=show_problem&problem=1556

题意:一个NXN棋盘,车管理横纵两条线,在任何一个车管理的区域都不能放与自己相同的颜色车。求最少可以用几种颜色涂车,使车两两之间不发生冲突,输出填色一组情况即可。

分析:

二分图匹配,
S (0< S < 10)
N(0 ≤ N ≤ 100)

构建二分图
1)对于二分图染色,染色种数总是等于每一行或每一列的棋子数
2)建边,使其构造成k阶正则二分图,正则二分图必有完备匹配
3)对每一种颜色,匹配出可以涂相同颜色的,然后涂上颜色,并删除这个点(此点已经涂了颜色,匹配了)
#include<iostream>
#include<cstdio>
#include<ctime>
#include<string.h>
#include<cstring>
#include<vector>

using namespace std;
const int maxn = 110;
char s[maxn][maxn];
vector<int> g[maxn];
int num[maxn][maxn],fg[maxn],link[maxn];
bool flag[maxn];
int n;
int rook;
void read()
{
scanf("%d",&n);
memset(s,0,sizeof(s));
memset(num,0,sizeof(num));
memset(fg,0,sizeof(fg));
rook = 0;
int ans ;
for(int i = 0;i<n;i++)
{
scanf("%s",s[i]);
g[i].clear();
ans = 0;
for(int j = 0;j<n;j++)
{
if(s[i][j] == '*')
{
ans++;
fg[j]++;
g[i].push_back(j);
}

}
rook = max(ans,rook);
}
for (int i = 0 ; i < n ; ++i)
{
ans = 0;
for (int j = n-1 ; j >= 0 ; --j)
if (s[j][i]=='*') ans++;
rook = max(rook,ans);
}
for(int i=0;i<n;i++)
{
if(g[i].size()<rook)
{
for(int j=0;j<n&&g[i].size()<rook;j++)
if(fg[j]<rook)
while(fg[j]<rook&&g[i].size()<rook)
{
g[i].push_back(j);
fg[j]++;
}

}
}
}
bool dfs(int x)
{
for(auto i=0;i<g[x].size();i++)
if(!flag[g[x][i]])
{
int y = g[x][i];
flag[y] = true;
if(link[y] == -1 || dfs(link[y]))
{
link[y] = x;
return true;
}
}
return false;
}

void maxmatch()
{
memset(link,-1,sizeof(link));
for(int i=0;i<n;i++)
{
memset(flag,false,sizeof(flag));
dfs(i);
}
}
void solve()
{
printf("%d\n",rook);
int color = 0;
int l,r;
memset(num,0,sizeof(num));
while(color < rook)
{
color++;
maxmatch();
for(int i=0;i<n;i++)
{
l= link[i];r=i;
if(s[l][r] == '*') num[l][r] = color;
for(auto j=0;j<g[l].size();j++) if(g[l][j] == r)
{
g[l].erase(g[l].begin()+j);
break;
}
}

}
}
void print()
{
for(int i =0;i<n;i++)
{
printf("%d",num[i][0]);
for(int j=1;j<n;j++)
printf(" %d",num[i][j]);
printf("\n");
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
read();
solve();
print();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: