题目描述

  给定一张\(n\)个点\(m\)条边的无向图。每个顶点有一个颜色,要么是黑,要么是白。我们想进行一些操作,使得最终每一条边的两个端点都是不同的颜色。每一次操作,你可以将一条边的两个端点交换颜色。求最少的操作次数和具体的操作方式。

  \(n\leq 500\)

题解

  首先黑白染色,假设要让染出来的黑点最终成为黑点,那么

   1.对于原来的每个黑点\(i\),连边\((S,i,1,0)\)

   2.对于染出来的每个黑点\(i\),连边\((i,T,1,0)\)

   3.对于原图中的每条边\((u,v)\),连边\((u,v,\infty,1),(v,u,\infty,1)\),表示交换两个端点的花费。

  跑完费用流后,每次bfs找到一条从\(S\)到\(T\)的路径,通过某些方法交换第一个点和最后一个点。

  对于一条长度大于\(1\)的路径,第一个点一定是白色的,最后一个点一定是黑色的。(第一个点靠\(T\),最后一个点靠\(S\))

  

  先把这个序列切成很多段,每段只有最右边的点是黑色的。

  

  把每段的黑点调到最前面

  

  再从后往前交换每段的第一个点和前一段的最后一个点。

  

  这样可以用长度\(-1\)步内交换第一个点和最后一个点。

  时间复杂度:\(O(???)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<queue>
#include<list>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
queue<int> q;
//vector<pii> a;
int ax[1000010];
int ay[1000010];
int len=0;
struct li
{
int h[510];
int v[100010];
int t[100010];
int n;
li()
{
memset(h,0,sizeof h);
n=0;
}
void add(int x,int y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
li l;
struct graph
{
int h[510];
int u[500010];
int v[500010];
int w[500010];
int c[500010];
int t[500010];
int p[500010];
int n;
void clear()
{
n=0;
memset(h,0,sizeof h);
}
void add(int x,int y,int z,int d)
{
n++;
u[n]=x;
v[n]=y;
w[n]=d;
c[n]=z;
p[n]=0;
t[n]=h[x];
h[x]=n;
}
int S,T;
int gd[510];
int gb[510];
int gf[510];
int flow,cost;
int f[510];
int op(int x)
{
return ((x-1)^1)+1;
}
int spfa()
{
memset(gd,0x7f,sizeof gd);
gd[S]=0;
gf[S]=0;
q.push(S);
int i,x;
while(!q.empty())
{
x=q.front();
q.pop();
gb[x]=0;
if(gd[x]>=gd[T])
continue;
for(i=h[x];i;i=t[i])
if(c[i]&&gd[v[i]]>gd[x]+w[i])
{
gd[v[i]]=gd[x]+w[i];
gf[v[i]]=i;
if(!gb[v[i]])
{
gb[v[i]]=1;
q.push(v[i]);
}
}
}
if(gd[T]==0x7f7f7f7f)
return 0;
flow++;
cost+=gd[T];
for(i=gf[T];i;i=gf[u[i]])
{
c[i]--;
p[i]++;
c[op(i)]++;
p[op(i)]--;
}
return 1;
}
int maxflow()
{
flow=cost=0;
while(spfa());
return cost;
}
int p1[500010];
int p2[500010];
void check()
{
memset(gb,0,sizeof gb);
gb[S]=1;
gf[S]=0;
q.push(S);
int i;
while(!q.empty())
{
int x=q.front();
q.pop();
for(i=h[x];i;i=t[i])
if(p[i]&&!gb[v[i]])
{
gb[v[i]]=1;
gf[v[i]]=i;
if(v[i]==T)
{
while(!q.empty())
q.pop();
return;
}
q.push(v[i]);
}
}
}
void getans()
{
check();
int i;
int t1=0,t2=0;
for(i=gf[T];i;i=gf[u[i]])
{
if(v[i]!=T)
p1[++t1]=v[i];
p[i]--;
}
for(i=t1;i>=2;i--)
if(f[p1[i-1]])
p2[++t2]=i;
else
{
// a.push_back(pii(p1[i-1],p1[i]));
ax[++len]=p1[i-1];
ay[len]=p1[i];
swap(f[p1[i]],f[p1[i-1]]);
}
for(i=t2;i>=1;i--)
{
// a.push_back(pii(p1[p2[i]],p1[p2[i]-1]));
ax[++len]=p1[p2[i]];
ay[len]=p1[p2[i]-1];
swap(f[p1[p2[i]]],f[p1[p2[i]-1]]);
}
}
};
graph g1,g2;
char s[510];
int c[510];
int from[510][510];
int d[510][510];
int vis[100010];
int s1,s2;
int b,w;
int ans;
list<int> e,e1,e2;
void failed()
{
printf("-1\n");
exit(0);
}
void dfs(int x,int p)
{
if(~vis[x])
{
if(vis[x]!=p)
failed();
return;
}
e.push_back(x);
vis[x]=p;
if(c[x])
b++;
else
w++;
if(p)
{
s1++;
e1.push_back(x);
}
else
{
s2++;
e2.push_back(x);
}
int i;
for(i=l.h[x];i;i=l.t[i])
dfs(l.v[i],p^1);
}
int build1()
{
for(auto v1:e)
{
int i;
for(i=l.h[v1];i;i=l.t[i])
{
int v2=l.v[i];
g1.add(v1,v2,1000,1);
g1.add(v2,v1,0,-1);
g1.add(v2,v1,1000,1);
g1.add(v1,v2,0,-1);
}
if(c[v1])
{
g1.add(g1.S,v1,1,0);
g1.add(v1,g1.S,0,0);
}
}
for(auto v1:e2)
{
g1.add(v1,g1.T,1,0);
g1.add(g1.T,v1,0,0);
}
return g1.maxflow();
}
int build2()
{
for(auto v1:e)
{
int i;
for(i=l.h[v1];i;i=l.t[i])
{
int v2=l.v[i];
g2.add(v1,v2,1000,1);
g2.add(v2,v1,0,-1);
g2.add(v2,v1,1000,1);
g2.add(v1,v2,0,-1);
}
if(c[v1])
{
g2.add(g2.S,v1,1,0);
g2.add(v1,g2.S,0,0);
}
}
for(auto v1:e1)
{
g2.add(v1,g2.T,1,0);
g2.add(g2.T,v1,0,0);
}
return g2.maxflow();
}
void rd(int &s)
{
int c;
while((c=getchar())<'0'||c>'9');
s=c-'0';
while((c=getchar())>='0'&&c<='9')
s=s*10+c-'0';
}
int main()
{
int n,m;
// scanf("%d%d",&n,&m);
rd(n);
rd(m);
int i;
scanf("%s",s+1);
for(i=1;i<=n;i++)
c[i]=s[i]-'0';
int x,y;
for(i=1;i<=m;i++)
{
// scanf("%d%d",&x,&y);
rd(x);
rd(y);
l.add(x,y);
l.add(y,x);
}
memset(vis,-1,sizeof vis);
ans=0;
g1.S=g2.S=n+1;
g1.T=g2.T=n+2;
for(i=1;i<=n;i++)
if(vis[i]==-1)
{
w=b=s1=s2=0;
e.clear();
e1.clear();
e2.clear();
dfs(i,0);
if(w!=s1&&w!=s2)
failed();
int ans1=0x7fffffff,ans2=0x7fffffff;
g1.clear();
g2.clear();
int f1,f2;
if(w==s1&&b==s2)
{
ans1=build1();
f1=g1.flow;
}
if(b==s1&&w==s2)
{
ans2=build2();
f2=g2.flow;
}
if(ans1<ans2)
{
ans+=ans1;
memcpy(g1.f,c,sizeof c);
while(f1--)
g1.getans();
}
else
{
ans+=ans2;
memcpy(g2.f,c,sizeof c);
while(f2--)
g2.getans();
}
}
printf("%d\n",ans);
// for(auto v:a)
// printf("%d %d\n",v.first,v.second);
for(i=1;i<=len;i++)
printf("%d %d\n",ax[i],ay[i]);
return 0;
}

【XSY1762】染色问题 网络流的更多相关文章

  1. 刷题总结——奇怪的游戏(scoi2012)

    题目: 题目描述 Blinker 最近喜欢上一个奇怪的游戏.这个游戏在一个 N*M  的棋盘上玩,每个格子有一个数.每次 Blinker  会选择两个相邻的格子,并使这两个数都加上 1.现在 Blin ...

  2. P3756 [CQOI2017]老C的方块

    题目链接 看到网格图+最优化问题,当然要想黑白染色搞网络流.不过这道题显然无法用黑白染色搞定. 仔细观察那四种图形,发现都是蓝线两边一定有两个格子,两个格子旁边一定还有且仅有一个格子.因此我们可以这么 ...

  3. CSP-S 2021 爆零记

    前言 本人今年高二蒟蒻OIer,高一刚刚接触OI. 感觉可能要直接退役了555~ 希望还有机会靠NOIP翻盘 Day - 暑假 为了备战CSP提前返校,与xzh一起划水,总之刷了不少题,我也大受震撼 ...

  4. 【线性规划与网络流 24题】已完成(3道题因为某些奇怪的原因被抛弃了QAQ)

    写在前面:SDOI2016 Round1滚粗后蒟蒻开始做网络流来自我拯救(2016-04-11再过几天就要考先修课,现在做网络流24题貌似没什么用←退役节奏) 做的题目将附上日期,见证我龟速刷题. 1 ...

  5. BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论

    这个题的数据,太卡了,TLE了两晚上,各种调试优化,各种蛋疼. 2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MB Submit ...

  6. 网络流系列算法总结(bzoj 3438 1061)

    网络流嘛,怎么看都是一堆逗逼题嘛,反正遇到还是都做不起嘛.... 网络流的模板非常简单,难点都在于建图,网络流的建图解决问题范围之广,下至A+B Problem,上至单纯形,线性规划.所以如果对于网络 ...

  7. 【HDU4859】 海岸线(网络流-最小割)

    Problem Description 欢迎来到珠海! 由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展.作为Z市的决策人,在仔细观察了Z市地图之后,你准备通过填充某些海域来扩 ...

  8. 「CODVES 1922 」骑士共存问题(二分图的最大独立集|网络流)&dinic

    首先是题目链接  http://codevs.cn/problem/1922/ 结果发现题目没图(心情复杂 然后去网上扒了一张图 大概就是这样了. 如果把每个点和它可以攻击的点连一条边,那问题就变成了 ...

  9. 洛谷P4003 无限之环(infinityloop)(网络流,费用流)

    洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ∗ m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格 ...

随机推荐

  1. Meterpreter常⻅见⽤用法

    0x01 背景 meterpreter作为后渗透模块有多种类型,并且命令由核⼼心命令和扩展库命令组成,极⼤大的丰富了了攻击⽅方式. 需要说明的是meterpreter在漏漏洞洞利利⽤用成功后会发送第二 ...

  2. springmvc的@ResponseBody报错

    错误:差不多就是下面的格式 原因:你可能返回的类型是这样的List<School>而school类中可能包含Class类或者Teacher类,就是包含对象. 这样的话jackson是不能帮 ...

  3. 将工程改造为SOA架构

    商城是基于soa的架构,表现层和服务层是不同的工程.所以要实现商品列表查询需要两个系统之间进行通信. 流动计算架构 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基 ...

  4. 日志之环绕通知(AOP)

    环绕通知:一个完整的try...catch...finally结构 编写环绕通知方法,环绕通知需要携带ProceedingJoinPoint 这个类型的参数,ProceedingJoinPoint类型 ...

  5. redis的应用场景 为什么用redis

    一.不是万能的菲关系系数据库redis 在面试的时候,常被问比较下Redis与Memcache的优缺点,个人觉得这二者并不适合一起比较,redis:是非关系型数据库不仅可以做缓存还能干其它事情,Mem ...

  6. Git文件冲突的常用解决方法

    在提交代码时,偶尔会有文件冲突的情况,当出现: Please, commit your changes or stash them before you can merge. 提示后,可用依次输入下列 ...

  7. 从零开始搭建VUE项目

    前言: 此样板面向大型,严肃的项目,并假定您对Webpack和vue-loader有些熟悉. 请务必阅读vue-loader的常见工作流配方的文档. 如果您只想尝试vue-loader或者鞭打一个快速 ...

  8. artTemplate精彩文章(个人阅读过)

    轻量级artTemplate引擎 实现前后端分离—基础篇 :https://www.imooc.com/article/20263 轻量级artTemplate引擎 实现前后端分离—语法篇 : htt ...

  9. mybatis异常解决:class path resource [SqlMapConfig.xml] cannot be opened because it does not exist

    解决方法: 缺失SqlMapConfig.xml文件.

  10. Linux在shell中进入python敲方向键出现「^[[C^[[D」的解决办法

    安装yum -y install readline-devel,然后在重新编译python