【XSY1762】染色问题 网络流
题目描述
给定一张\(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】染色问题 网络流的更多相关文章
- 刷题总结——奇怪的游戏(scoi2012)
题目: 题目描述 Blinker 最近喜欢上一个奇怪的游戏.这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1.现在 Blin ...
- P3756 [CQOI2017]老C的方块
题目链接 看到网格图+最优化问题,当然要想黑白染色搞网络流.不过这道题显然无法用黑白染色搞定. 仔细观察那四种图形,发现都是蓝线两边一定有两个格子,两个格子旁边一定还有且仅有一个格子.因此我们可以这么 ...
- CSP-S 2021 爆零记
前言 本人今年高二蒟蒻OIer,高一刚刚接触OI. 感觉可能要直接退役了555~ 希望还有机会靠NOIP翻盘 Day - 暑假 为了备战CSP提前返校,与xzh一起划水,总之刷了不少题,我也大受震撼 ...
- 【线性规划与网络流 24题】已完成(3道题因为某些奇怪的原因被抛弃了QAQ)
写在前面:SDOI2016 Round1滚粗后蒟蒻开始做网络流来自我拯救(2016-04-11再过几天就要考先修课,现在做网络流24题貌似没什么用←退役节奏) 做的题目将附上日期,见证我龟速刷题. 1 ...
- BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论
这个题的数据,太卡了,TLE了两晚上,各种调试优化,各种蛋疼. 2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MB Submit ...
- 网络流系列算法总结(bzoj 3438 1061)
网络流嘛,怎么看都是一堆逗逼题嘛,反正遇到还是都做不起嘛.... 网络流的模板非常简单,难点都在于建图,网络流的建图解决问题范围之广,下至A+B Problem,上至单纯形,线性规划.所以如果对于网络 ...
- 【HDU4859】 海岸线(网络流-最小割)
Problem Description 欢迎来到珠海! 由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展.作为Z市的决策人,在仔细观察了Z市地图之后,你准备通过填充某些海域来扩 ...
- 「CODVES 1922 」骑士共存问题(二分图的最大独立集|网络流)&dinic
首先是题目链接 http://codevs.cn/problem/1922/ 结果发现题目没图(心情复杂 然后去网上扒了一张图 大概就是这样了. 如果把每个点和它可以攻击的点连一条边,那问题就变成了 ...
- 洛谷P4003 无限之环(infinityloop)(网络流,费用流)
洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ∗ m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格 ...
随机推荐
- 内置函数二: map sorted filter
-----------生活里没有奇迹,大部分的时候奇迹是你自己创造的. # -------------------------------------------------------------- ...
- Zk搭建(Zookeeper)
第一步: 上传----解压 tar -zxvf zookeeper-3.4.5.tar.gz---- 配置zk的环境变量 ----------配置源码 vim ...
- 解决linux用户切换失败 su:execute /usr/bin 没有权限
问题描述: 回宿舍前,在root用户中安装fish,并修改其shell为fish.回宿舍之后,在图形界面用root用户进行登陆,莫名其妙登陆失败.没有任何提示信息,直接回到登陆界面.用非root用户登 ...
- Requires: libc.so.6(GLIBC_2.14)(64bit)
centos6 - CentOS 6 - libc.so.6(GLIBC_2.14)(64bit) is needed by - Server Faulthttps://serverfault.com ...
- marMariaDB & MYSQL flexviews
Using Flexviews - part one, introduction to materialized views - Percona Database Performance Bloght ...
- HTTL之初印象
概述 HTTL (Hyper-Text Template Language) 是一个高性能的开源JAVA模板引擎, 适用于动态HTML页面输出, 可替代JSP页面, 指令和Velocity相似. 简洁 ...
- gulp项目和webpack项目在浏览器中查看的方式
在存在.git的目录下,按住shift+左键,打开命令行或者使用git Bash Gulp: 输入gulp dev 本地起一个服务器,在项目中找到gulp.js,然后找本地服务器,找到host和por ...
- java核心API学习
1:java.lang (Object.String.StringBuffer.Thread.System.ClassLoader.Class.Runtime.包装类等)
- 面试题(校招java)
1:linux线程和进程的区别? 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程 ...
- 4面向对象(OOP)
学习线路 初学: 熟悉语法 进阶: 1.23种设计模式 2.6中开发原则 高级: 1.优化 2.架构 3.安全 概念 类:一类具有相同特性的事物的抽象描述,用一个java类表示. 成员变量:抽取的属性 ...