【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 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格 ...
随机推荐
- Dockerfile centos7_php5.6.36
Dockerfile: FROM centos:7 MAINTAINER www.ctnrs.com RUN yum install epel-release -y && \ yum ...
- Java面试题详解三:比较器
一,Comparable和Comparator1.Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较.Comparable接口中只有一 ...
- 【学习总结】Git学习-参考廖雪峰老师教程五-远程仓库
学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...
- PyCharm中快速给选中的代码加上{}、<>、()、[]
快捷键Ctrl + Shift + S 呼出下图所示界面:
- tomcat one connection one thread one request one thread
java - What is the difference between thread per connection vs thread per request? - Stack Overflow ...
- Jenkins deploy war to tomcat over https
ssl - HTTPS login with Spring Security redirects to HTTP - Stack Overflow https://stackoverflow.com/ ...
- Jmeter监控服务器笔记
Jmeter监控服务器-CPU,Memory,Disk,Network性能指标 本文主要说一下如何通过JMeter插件来监控服务器CPU.内存.磁盘.网络等相关资源. 一.下载 首先进入网址https ...
- css 图片文字垂直居中
先来看张图片 相信很多css新手遇到过这种问题,就是当图片和文本显示在一行的时候,效果很奇葩,文字和图片没法对齐, 这时我们需要做的是: 1,先给块级元素设置 display: inline-bloc ...
- VS如何在调试时进入到dll文件
背景: 项目A:用C#写的一个类库文件 项目B:引用项目A的dll文件,完成编码,也是C#编写的. 需求:怎么能在调试的时候,调试断点能够从项目B中进入项目A中的代码. 解决办法就是: 假设,项 ...
- laravel实现批量添加数据
在使用laravel eloquent进行数据库操作的时候惊讶的发现这货居然不支持批量添加,看到网上很多人在循环里进行数据库插入操作来实现批量添加,我想说这样做是很损失性能滴!好在框架的DB门面里的i ...