HDU5740 Glorious Brilliance【最短路 KM匹配】
HDU5740 Glorious Brilliance
题意:
给出一张不一定合法的染色图,每次可以交换相邻两点的颜色,问最少多少次能使染色图合法
合法的染色图相邻点的颜色不能相同
题解:
首先要确定原图中是否存在染色图,如果不存在直接输出\(-1\)
其次确定给定的两种颜色数量是否能够染出一张合法的染色图,如果数量不对输出\(-1\)
可以发现对于节点\(u,v\),交换两者的颜色最少需要操作两者\(dist_{u,v}\)次,并且可以保证路径中间点的颜色不变
指针先指向最左边点,然后右指针向右找到第一个和左指针所指颜色不同的点,把右侧点不断和左边的点换,然后把左指针指向右指针所指点,继续操作
所以我们需要将两种颜色的点两两匹配,使得最短路的和最小,用KM匹配即可,最后输出路径,就按上述方法输出即可
注意要对每一块连通图单独处理
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 555;
const int INF = 0x3f3f3f3f;
int n,m,col[MAXN],tpcol[MAXN],ID;
int dist[MAXN][MAXN], pre[MAXN][MAXN];
char buf[MAXN];
vector<int> G[MAXN],pt[MAXN];
bool setColor(int x, int id){ // 染色
queue<int> que;
que.push(x);
tpcol[x] = 0;
while(!que.empty()){
int u = que.front();
que.pop();
pt[id].push_back(u);
for(int v : G[u]){
if(tpcol[v]!=-1){
if(tpcol[v]==tpcol[u]) return false;
continue;
}
tpcol[v] = tpcol[u] ^ 1;
que.push(v);
}
}
return true;
}
void getPath(int x){ // 计算最短路和最短路路径
memset(dist[x]+1,0x3f,n<<2);
dist[x][x] = 0;
pre[x][x] = -1;
queue<int> que;
que.push(x);
while(!que.empty()){
int u = que.front();
que.pop();
for(int v : G[u]){
if(dist[x][v]!=INF) continue;
dist[x][v] = dist[x][u] + 1;
pre[x][v] = u;
que.push(v);
}
}
}
int match[MAXN],visx[MAXN],visy[MAXN],lx[MAXN],ly[MAXN],slack[MAXN];
vector<int> lft,rht;
bool dfs(int u){
visx[u] = true;
for(int v : rht){
if(visy[v]) continue;
int gap = dist[u][v] - lx[u] - ly[v];
if(!gap){
visy[v] = true;
if(match[v]==-1 or dfs(match[v])){
match[v] = u;
return true;
}
}
else slack[v] = min(slack[v],gap);
}
return false;
}
int KM(int id, int tag){
lft.clear(); rht.clear();
for(int x : pt[id]){
if((col[x]^tag)==tpcol[x]) continue;
if(col[x]==0) lft.push_back(x);
else rht.push_back(x);
}
if(lft.size()!=rht.size()) return INF;
for(int x : lft){
lx[x] = INF;
for(int y : rht) lx[x] = min(lx[x],dist[x][y]);
}
for(int x : rht){
match[x] = -1;
ly[x] = 0;
}
for(int x : lft){
for(int y : rht) slack[y] = INF;
while(true){
for(int xx : lft) visx[xx] = false;
for(int yy : rht) visy[yy] = false;
if(dfs(x)) break;
int d = INF;
for(int yy : rht) if(!visy[yy]) d = min(d,slack[yy]);
for(int xx : lft) if(visx[xx]) lx[xx] += d;
for(int yy : rht){
if(!visy[yy]) slack[yy] -= d;
else ly[yy] -= d;
}
}
}
int tot = 0;
for(int y : rht) tot += dist[y][match[y]];
return tot;
}
vector<pair<int,int> > path;
void record(int id, int tag){
KM(id,tag);
for(int y : rht){
int x = match[y];
vector<int> route;
int u = y;
while(u!=-1){
route.push_back(u);
u = pre[x][u];
}
int sz = (int)route.size();
int l = 0;
while(l!=sz-1){
int r = l;
while(col[route[r]]==col[route[r+1]]) r++;
r++;
for(int i = r; i > l; i--) path.push_back(make_pair(route[i],route[i-1]));
swap(col[route[l]],col[route[r]]);
l = r;
}
}
}
void solve(){
scanf("%d %d %s",&n,&m,buf+1);
for(int i = 1; i <= n; i++) col[i] = buf[i] - '0';
for(int i = 1; i <= n; i++) G[i].clear();
for(int i = 1; i <= n; i++) tpcol[i] = -1;
for(int i = 1; i <= m; i++){
int u, v; scanf("%d %d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
ID = 0;
bool flag = false;
for(int i = 1; i <= n; i++) getPath(i);
path.clear();
for(int i = 1; i <= n; i++) if(tpcol[i]==-1){
pt[++ID].clear();
if(!setColor(i, ID)){
flag = true;
break;
}
int c0 = 0, c1 = 0;
int tpc0 = 0, tpc1 = 0;
for(int x : pt[ID]){
if(col[x]==0) c0++;
else c1++;
if(tpcol[x]==0) tpc0++;
else tpc1++;
}
if(c0!=tpc0 and c0!=tpc1){
flag = true;
break;
}
int mt0 = INF, mt1 = INF;
if(c0==tpc0) mt0 = KM(ID,0);
if(c0==tpc1) mt1 = KM(ID,1);
if(mt0==INF and mt1==INF){
flag = true;
break;
}
if(mt0<mt1) record(ID,0);
else record(ID,1);
}
if(flag){
puts("-1");
return;
}
printf("%d\n",path.size());
for(auto p : path) printf("%d %d\n",p.first,p.second);
}
int main(){
int tt;
for(scanf("%d",&tt); tt; tt--) solve();
return 0;
}
HDU5740 Glorious Brilliance【最短路 KM匹配】的更多相关文章
- Glorious Brilliance (最短路 + 带权二分图匹配)
这是一道代码大题.一开始读错题意了,然后理解成直接看上去的那种相邻,然后想不通好久!!! 把不同联通的图分离出来,然后先预处理一下形成之后的相邻图的状态,然后根据01确定哪一些是需要更换状态的,然后建 ...
- 【转】KM匹配题集
转自:http://blog.csdn.net/shahdza/article/details/7779324 [HDU]2255 奔小康赚大钱 模板题★1533 Going Home 模板题★242 ...
- HDU 5740 - Glorious Brilliance
题意: 给出已0 1染色的无向图(不一定联通),一次操作为一对相邻点颜色互换. 问使任意相邻点颜色不同,最少需要多少次操作 分析: 交换两点的代价即为两点间最短路. 故用BFS找出所有点到任意点的最短 ...
- KM匹配板子
/* gyt Live up to every day */ #include<cstdio> #include<cmath> #include<iostream> ...
- 【转载】图论 500题——主要为hdu/poj/zoj
转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...
- 【HDOJ图论题集】【转】
=============================以下是最小生成树+并查集====================================== [HDU] How Many Table ...
- hdu图论题目分类
=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many ...
- HDU图论题单
=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many ...
- POJ 2516 Minimum Cost (KM最优匹配)
题意:有N家家店,每家店都对K种货物有需求:同时有M家仓库,对K钟货物有供应.对于每种货物,每个仓库送至每家店都有自己的单位费用.求满足所有店所有货物的最小费用 分析:对于每一种货物,如果总需求大于总 ...
随机推荐
- Redis核心原理-简单动态字符串SDS
SDS简介 Redis是C语言编写的,但没有使用c语言的字符串结构,而是自己实现了一套简单动态字符串 simple dynamic string 简称SDS,SDS兼容C语言的字符串类型,原理类似Ja ...
- LeetCode498 对角线遍历
给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示. 示例: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], ...
- Svm算法原理及实现
Svm(support Vector Mac)又称为支持向量机,是一种二分类的模型.当然如果进行修改之后也是可以用于多类别问题的分类.支持向量机可以分为线性核非线性两大类.其主要思想为找到空间中的一个 ...
- 天梯赛练习 L3-011 直捣黄龙 (30分) dijkstra + dfs
题目分析: 本题我有两种思路,一种是只依靠dijkstra算法,在dijkstra部分直接判断所有的情况,以局部最优解得到全局最优解,另一种是dijkstra + dfs,先计算出最短距离以及每个点的 ...
- 天梯赛练习 L3-010 是否完全二叉搜索树 (30分) 数组建树模拟
题目分析: 本题的要求是将n个数依次插入一个空的二叉搜索树(左大右小,且没有重复数字),最后需要输出其层次遍历以及判断是否是完全二叉搜索树,通过观察我们发现, 如果这个树是用数组建立的,那么最后输出的 ...
- [从源码学设计]蚂蚁金服SOFARegistry之续约和驱逐
[从源码学设计]蚂蚁金服SOFARegistry之续约和驱逐 目录 [从源码学设计]蚂蚁金服SOFARegistry之续约和驱逐 0x00 摘要 0x01 业务范畴 1.1 失效剔除 1.2 服务续约 ...
- su3和SU01中参数说明
对于SU3和SU01中的的"参数"tab栏中的参数可以自己添加和删除. 所有的参数都存在表TPARA中,并且有对应的参数的说明. 那么这些参数如何使用呢? 通常的使用是,通过类似 ...
- django使用缓存之drf-extensions
使用方法:1.直接添加装饰器@cache_response该装饰器装饰的方法有两个要求: 它必须是继承了rest_framework.views.APIView的类的方法 它必须返回rest_fram ...
- MySQL简介及安装 mysql Ver 14.14 Distrib 5.7.28
1.MySQL简介 1.数据库产品演变 第一代数据库架构: RDBMS 关系型数据库时代 : 合的时代 代表产品 :Oracle .MSSQL .MySQL.SQL server 第二代数据库架构:拆 ...
- 知识图谱KnowledgeGraph核心技术培训班 2月03日— 2月06日