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)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后, ...
随机推荐
- Python开发【笔记】:列表转字典
列表转字典 it = [1,2,3,4] print(dict(zip(it, it))) # {1: 1, 2: 2, 3: 3, 4: 4} it = iter(it) print(dict(zi ...
- 集齐所有机制的按键控制LED驱动
内核版本:linux2.6.22.6 硬件平台:JZ2440 驱动源码 final_key.c : #include <linux/module.h> #include <linux ...
- ubuntu14.04下开启ssh服务
1. 安装 sudo apt-get update sudo apt-get install openssh-server 2.开启服务 查看查看ssh服务是否启动 打开"终端窗口" ...
- InnoDB表回收空间
当innodb_file_per_table设置为OFF,那么所有数据将被存储在ibdata文件.如果删除一些数据和删除一些表则没有回收未使用的磁盘空间,除了导出表然后再导入的方法来回收表空间大小,除 ...
- NPM常用命令install 淘宝镜像 update等
NPM是随同NodeJS一起安装的包管理工具,允许用户从NPM服务器上传下载安装第三方包或命令行程序,能解决NodeJS代码部署上的很多问题,非常方便.下面我们一起来看看常用的npm命令有哪些 使用方 ...
- UITextView设置placeholder
下面是我的代码,可以直接拿来用 #import <UIKit/UIKit.h> @interface CustomTextView : UITextView @property(nonat ...
- pandas操作速查表
准备工作 import numpy as np import pandas as pd 倒入文件或创建一个数据表 df = pd.DataFrame(pd.read_csv('name.csv',he ...
- 对比库表结构,生成SQL
网上找了一圈对比库的工具,能手工生成差别的SQL的工具没有,改造了一下网上的sql 1, 获取字段名的类型 create FUNCTION [dbo].[getColType](@tab varcha ...
- 004-RestTemplate 使用常见问题
一.使用 同前三节:ClientGetGoodsByGoodsIdResponse response = restTemplate.postForObject(svcUrl, request, Res ...
- 香港低价linux虚拟主机,
https://www.sugarhosts.com/zh-cn/hosting/shared-web-hosting Shared Baby 36 个月 ¥ 26.99 19 99 · / 月 续费 ...