这是一道代码大题。一开始读错题意了,然后理解成直接看上去的那种相邻,然后想不通好久!!!

把不同联通的图分离出来,然后先预处理一下形成之后的相邻图的状态,然后根据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 (最短路 + 带权二分图匹配)的更多相关文章

  1. POJ 2195 Going Home (带权二分图匹配)

    POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...

  2. 运动员最佳匹配问题 KM算法:带权二分图匹配

    题面: 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势:Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势. ...

  3. 费用流模板(带权二分图匹配)——hdu1533

    /* 带权二分图匹配 用费用流求,增加源点s 和 汇点t */ #include<bits/stdc++.h> using namespace std; #define maxn 1000 ...

  4. POJ 2195 Going Home | 带权二分图匹配

    给个地图有人和房子 保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价 问让人都住在房子里最小代价 显然是个带权二分图最大匹配 转化成以一个网络,规定w是容量,c是代价 1.S向人连边,w=1 ...

  5. hdu5045:带权二分图匹配

    题目大意 : n个人 做m道题,其中 每连续的n道必须由不同的人做 已知第i人做出第j题的概率为pij,求最大期望 思路:考虑每连续的n道题 都要n个人来做,显然想到了带权的二分图匹配 然后就是套模板 ...

  6. [NOI2012]美食节——费用流(带权二分图匹配)+动态加边

    题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...

  7. [HAOI2008]移动玩具(状压&带权二分图)

    题目描述 • 一个 4 × 4 的 0/1 矩阵 • 每次可以交换相邻两个元素 • 求从初始状态到目标状态的最小交换次数 输入格式 前四行,每行一个长为 4 的 0/1 字符串,描述初始状态. 后四行 ...

  8. Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配)

    Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配) Description 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的 ...

  9. KM(Kuhn-Munkres)算法求带权二分图的最佳匹配

    KM(Kuhn-Munkres)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后, ...

随机推荐

  1. Java之旅_高级教程_URL处理

    摘自 :http://www.runoob.com/java/java-url-processing.html Java URL 处理 URL(Uniform Resource Locator)中文名 ...

  2. js数组方法汇总

    下面主要汇总一下数组的方法 数组方法: 1.检测是否为数组的方法:Array.isArrray(); var arr=[1,2,3,4,5]; var str='string'; console.lo ...

  3. kali蓝牙连接

    http://blog.csdn.net/hailangnet/article/details/47723181 http://www.aiuxian.com/article/p-3012084.ht ...

  4. 爬虫请求库——selenium

    selenium模块 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题.selenium的缺点是效率会变得很慢. sel ...

  5. javascript篇-console.log()打印object却显示为字符串[object object]

    console.log打印对象遇到的一个问题,如下截图 打印结果与预期不符,原因是因为字符串‘a’和对象object拼接在一起,拼成了一个字符串

  6. Ubuntu Server16.04 配置网卡

    展示全部启动网卡 $ ifconfig 配置网卡 $ sudo vi /etc/network/interfaces auto enp2s0 iface enp2s0 inet static addr ...

  7. Python 全栈开发三 python基础 条件与循环

    一. 条件语句 python条件语句是根据一条或多条语句的执行结果的真假(True Or False)来决定代码块的执行. 而执行内容可以多行,以缩进来区分表示同一范围. 1.Python判断条件真假 ...

  8. DLNg序列模型第二周NLP与词嵌入

    1.使用词嵌入 给了一个命名实体识别的例子,如果两句分别是“orange farmer”和“apple farmer”,由于两种都是比较常见的,那么可以判断主语为人名. 但是如果是榴莲种植员可能就无法 ...

  9. windows下使用pyinstaller把python文件打包成exe可执行文件

    使用pyinstaller打包有个好处就是所有依赖都打包进去了,可以随意把文件移动到别的电脑上使用 安装 pip install pyinstaller 新建一个demo.py文件 #!/usr/bi ...

  10. 我的Chrome插件

    1.AdBlock 用来屏蔽广告,用过的人都说好. 2.Flash Block(Plus) 用来限制Flash的播放. 3.Flash Control 用来限制Flash的播放. 4.Full Pag ...