Glorious Brilliance (最短路 + 带权二分图匹配)
这是一道代码大题。一开始读错题意了,然后理解成直接看上去的那种相邻,然后想不通好久!!!
把不同联通的图分离出来,然后先预处理一下形成之后的相邻图的状态,然后根据01确定哪一些是需要更换状态的,然后建图,利用二分图KM算法去匹配最优方案。然后求出每一组更换的,利用原先已经求好的路径去储存答案。
#include<bits/stdc++.h>
using namespace std; const int inf = 0x3f3f3f3f;
const int maxn = 5e2 + ;
vector<pair<int, int> >ANS;
vector<int>Gra[maxn], path[maxn][maxn], X, Y, Left, Right;
char str[maxn];
int g[maxn][maxn], col[maxn], *pairr, pairr1[maxn], pairr2[maxn];
int mp[maxn][maxn], lx[maxn], ly[maxn], linker[maxn], slack[maxn];
int n, m, l, nx, ny;
bool vis[maxn], visx[maxn], visy[maxn]; bool DFS(int x){
visx[x] = true;
for(int y = ; y < ny; y++) {
if(visy[y])
continue;
int tmp = lx[x] + ly[y] - mp[x][y];
if(tmp == ) {
visy[y] = true;
if(linker[y] == - || DFS(linker[y])) {
linker[y] = x;
return true;
}
} else if(slack[y] > tmp)
slack[y] = tmp;
}
return false;
} int KM(){
memset(linker,-,sizeof(linker));
memset(ly,,sizeof(ly));
for(int i = ; i < nx; i++) {
lx[i] = -inf;
for(int j = ; j < ny; j++)
if(mp[i][j] > lx[i])
lx[i] = mp[i][j];
}
for(int x = ; x < nx; x++) {
for(int i = ; i < ny; i++)
slack[i] = inf;
while(true) {
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
if(DFS(x))
break;
int d = inf;
for(int i = ; i < ny; i++)
if(!visy[i] && d > slack[i])
d = slack[i];
for(int i = ; i < nx; i++)
if(visx[i])
lx[i] -= d;
for(int i = ; i < ny; i++) {
if(visy[i])
ly[i] += d;
else
slack[i] -= d;
}
}
}
int res = ;
for(int i = ; i < ny; i++)
if(linker[i] != -)
res -= mp[linker[i]][i];
return res;
} void getMinRoad(int u){
queue<int>que;while(!que.empty())que.pop();
que.push(u);g[u][u] = ;
path[u][u].push_back(u);
memset(vis, false, sizeof(vis));
vis[u] = true; while(!que.empty()){
int st = que.front();que.pop(); for(auto to : Gra[st]){
if(vis[to]) continue;
vis[to] = true;
g[u][to] = g[u][st] + ;
path[u][to] = path[u][st];
path[u][to].push_back(to);
que.push(to);
}
}
} bool color(int st){
queue<int> que;while(!que.empty())que.pop();
X.push_back(st);
que.push(st);
col[st] = ;
while(!que.empty()){
int u = que.front();que.pop(); for(auto v : Gra[u]){
if(col[v] == col[u]) return false;
if(col[v] != -) continue;
col[v] = col[u] ^ ;
if(col[v]) Y.push_back(v);
else X.push_back(v); que.push(v);
}
}
return true;
} void GetAns(int u, int v, int setp){
if(u == v) return ;
vector<int>&tmp = path[u][v];
for(int i = ; i < tmp.size() - ; i ++)
if(str[tmp[i]] != str[tmp[i +]]){
ANS.push_back(make_pair(tmp[i], tmp[i + ]));
swap(str[tmp[i]], str[tmp[i + ]]);
GetAns(u, tmp[i], setp + );
GetAns(tmp[i + ], v, setp + );
return ;
}
} int getSum(vector<int>A, vector<int>B, int Pair[]){
Left.clear(); Right.clear();
for(auto x : A) if(str[x] == '') Left.push_back(x);
for(auto x : B) if(str[x] == '') Right.push_back(x); nx = ny = Left.size();
for(int i = ; i < nx; i ++)
for(int j = ; j < ny; j ++)
mp[i][j] = - g[Left[i]][Right[j]];
int ret = KM(); for(int i = ; i < nx; i ++){
int u = Right[i], v = Left[linker[i]];
Pair[u] = v;Pair[v] = u;
}
return ret;
} bool solve(int st){
int zero = , sum1 = inf, sum2 = inf;
X.clear(), Y.clear();
if(!color(st)) return ;
for(auto x : X) if(str[x] == '') zero ++;
for(auto x : Y) if(str[x] == '') zero ++; if(zero == X.size()) sum1 = getSum(X, Y, pairr1);
if(zero == Y.size()) sum2 = getSum(Y, X, pairr2); if(sum1 == inf && sum2 == inf) return false;
pairr = sum1 > sum2 ? pairr2 : pairr1;
for(auto x : X) if(pairr[x] != -) GetAns(x, pairr[x], ); return true;
} void init(){
memset(pairr1, -, sizeof(pairr1));
memset(pairr2, -, sizeof(pairr2));
memset(slack, , sizeof(slack));
for(int i = ; i <= n; i ++){
Gra[i].clear();
col[i] = -;
for(int j = ; j <= n; j ++){
g[i][j] = inf;
path[i][j].clear();
}
}
ANS.clear();
} int main(){
int T,a,b;scanf("%d",&T);
while(T --){
scanf("%d%d%s", &n, &m, str + );
init();
for(int i = ; i < m; i ++){
scanf("%d%d",&a,&b);
Gra[a].push_back(b);
Gra[b].push_back(a);
}
for(int i = ; i <= n; i ++) getMinRoad(i); bool flag = true;
for(int i = ; i <= n; i ++){
if(col[i] == - && !solve(i)){
flag = false;break;
}
}
if(!flag){
printf("-1\n");
continue;
}
printf("%d\n", ANS.size());
for(int i = ; i < ANS.size(); i ++){
printf("%d %d\n",ANS[i].first, ANS[i].second);
}
}
return ;
}
Glorious Brilliance (最短路 + 带权二分图匹配)的更多相关文章
- POJ 2195 Going Home (带权二分图匹配)
POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...
- 运动员最佳匹配问题 KM算法:带权二分图匹配
题面: 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势:Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势. ...
- 费用流模板(带权二分图匹配)——hdu1533
/* 带权二分图匹配 用费用流求,增加源点s 和 汇点t */ #include<bits/stdc++.h> using namespace std; #define maxn 1000 ...
- POJ 2195 Going Home | 带权二分图匹配
给个地图有人和房子 保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价 问让人都住在房子里最小代价 显然是个带权二分图最大匹配 转化成以一个网络,规定w是容量,c是代价 1.S向人连边,w=1 ...
- hdu5045:带权二分图匹配
题目大意 : n个人 做m道题,其中 每连续的n道必须由不同的人做 已知第i人做出第j题的概率为pij,求最大期望 思路:考虑每连续的n道题 都要n个人来做,显然想到了带权的二分图匹配 然后就是套模板 ...
- [NOI2012]美食节——费用流(带权二分图匹配)+动态加边
题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...
- [HAOI2008]移动玩具(状压&带权二分图)
题目描述 • 一个 4 × 4 的 0/1 矩阵 • 每次可以交换相邻两个元素 • 求从初始状态到目标状态的最小交换次数 输入格式 前四行,每行一个长为 4 的 0/1 字符串,描述初始状态. 后四行 ...
- Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配)
Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配) Description 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的 ...
- KM(Kuhn-Munkres)算法求带权二分图的最佳匹配
KM(Kuhn-Munkres)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后, ...
随机推荐
- Web Deploy远程部署配置图解
原文链接:https://jingyan.baidu.com/album/642c9d34e614de644a46f783.html
- WebDriver一些常见问题的解决方法
1.Exception NoSuchElementException: 解决方法: 1)检查目标element的locator 2)如果locator是正确的,尝试在查找element之前等待页面的加 ...
- Loadrunner回放脚本时报错Action.c(41): Error -27979: Requested form not found [MsgId: MERR-27979]
解决方法 打开录制选项配置对话框进行设置,在“Recording Options”的“Internet Protocol”选项里的“Recording”中选择“Recording Level”为“HT ...
- ReentrantLock可重入锁的原理及使用场景
摘要 从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些. 场景1:如果已加锁,则不再重复加锁 a.忽略重复加锁.b.用在界面交互时点击执行较长时间请求操作时,防止多次 ...
- 如何暂停和继续运行Linux程序
我们通过shell窗口运行程序时,由于有的程序长时间运行,直到下班了都还没有返回运行结果.这个时候,我们又不能直接关闭shell窗口,不然前面的时间就白白运行了. 那有什么办法可以先暂停程序,明天再继 ...
- 爬虫请求库——requests
请求库,即可以模仿浏览器对网站发起请求的模块(库). requests模块 使用requests可以模拟浏览器的请求,requests模块的本质是封装了urllib3模块的功能,比起之前用到的urll ...
- git命令操作的时候,出现中文名显示问题
方法一:git config --global core.quotepath false 方法二: Windows系统的Git默认是不支持中文显示的,需要进行一系列的设置才能避免乱码的出现,下面总结如 ...
- bootbox.js官方文档中文版
bootbox.js官方文档中文版简介:Bootbox.js是一个小型的JavaScript库,基于Bootstrap模态框开发,用于创建可编程的对话框. 不像原生的alert等对话框,所有的Boot ...
- 遇到Visual Studio "当前不会命中断点.还没有为该文档加载任何符号"的情况
一.问题及原因 有这样一种调用逻辑:A.exe调用B.dll.现在想要在B的源代码中打断点,从A发起进行调试,却给出了"当前不会命中断点.还没有为该文档加载任何符号"的提示.感觉十 ...
- javascript 及 vue 中的变量前面的美元符号 $ 是什么意思
$ 您会注意到,我们将库代理为以美元符号“$”为前缀的属性名. 你可能还看过其他的属性和方法,例如,$refs, $on, $mount等等也都是以”$”开头. 虽然属性名上添加前缀不是必须的,但是这 ...