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)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后, ...
随机推荐
- 用promise和async/await分别实现红绿灯
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Python网络爬虫第三弹《爬取get请求的页面数据》
一.urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求.其常被用到的子模块在Python3中的为urllib.request和urllib. ...
- 关于mobilesroll使用方法的再次声明
js $('#name').click(function(valueText) { $('#demo').mobiscroll('show'); // return false; }); $(&quo ...
- 云锁-安全,易用,灵活的许可-Virbox许可管理平台
云许可,助力开发者保护软件财富 Virbox 云锁提供高强度加密及软件许可管理功能 安全,易用,灵活 防破解 云许可安全性体验与硬件锁一致,避免盗版导致损失 加密保护技术:反黑引擎/碎片代码执行/虚拟 ...
- log4j。日志输出
log4j.rootLogger = debug , stdout , D , E log4j.appender.stdout = org.apache.log4j.ConsoleAppender l ...
- python 常见报错汇总
python官方文档:https://docs.python.org/zh-cn/3/tutorial/index.html 1.indentationerror:unindent does not ...
- 密码登录源码(jsp+java+数据库)
jsp界面: <%@ page language="java" contentType="text/html; charset=utf-8" pageEn ...
- go https ajax
这个很好用啊,估计大有用武之地 你会喜欢 //https-ajax.go package main import ( "fmt" "io" "net/ ...
- iOS 聊天表情键盘
具体思路 通过UIKeyboardWillChangeFrameNotification通知,监听键盘的改变,同时可以得到键盘的Frame和动画的持续时间, 新建键盘顶部工具条YSComposeToo ...
- iOS 开发笔记-报错处理
1.xcode7报错:does not contain bitcode 解决方法:Build Settings 搜索 bitcode 将Enable Bitcode更改为NO即可 2.Code Si ...