[HAOI2017]新型城市化 二分图+网络流+关键边
时间:2019-03-25
本文章向大家介绍[HAOI2017]新型城市化 二分图+网络流+关键边,主要包括[HAOI2017]新型城市化 二分图+网络流+关键边使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
HAOI2017
- emm。一道模板题,本来想着30分钟写完,一点半赶紧开始打比赛……没想到,看题目理解题意花了20分钟,敲了10分钟。比赛完之后,写了30分钟吧,交上去果断0分。晚上调整思路之后,又写了一遍,仍然是0分。
在神犇帮助下,找到了自己的错误:用网络流跑最大匹配,建的边都是有向边!
Solution
- 题目给定\(m\)对点对,这\(m\)对点对互相之间没有连边。其他的点互相之间都有边,问:把哪个点对连通之后,最大团会变大。
- 在原图中是添加边使得最大团变大,对应在补图中当然就是割一条边,使得最大独立集变大。
- 最大独立集=点数-最大匹配数。那么就是割一条边使得最大匹配数变小。也就是求二分图关键边。
- 图中已经保证没有奇环,所以直接二分图染色。
- 建边跑最大流。
tarjan求scc,判断关键边。
Coding
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e4+10;
const int M=4e6+10;
const int inf=1e9;
struct node{
int x,y,id1,id2;
}e[M],f[M];
int n,m,S,T,num,top,cnt,tot,flow,maxflow,lin[N],Next[M],ver[M],edge[M],dfn[N],low[N],ins[N],s[N],c[N],d[N],color[N];
int read(){
char ch=getchar();int num=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){num=(num<<1)+(num<<3)+(ch^48);ch=getchar();}
return num*f;
}
void dfs(int x,int col){
color[x]=col;
for(int i=lin[x];i;i=Next[i]){
int y=ver[i];
if(!color[y]) dfs(y,3-col);
}
}
void add(int x,int y){ver[++tot]=y;Next[tot]=lin[x];lin[x]=tot;}
void Add(int x,int y,int z){
ver[++tot]=y;Next[tot]=lin[x];lin[x]=tot;edge[tot]=z;
ver[++tot]=x;Next[tot]=lin[y];lin[y]=tot;edge[tot]=0;
}
bool bfs(){
queue<int>q;
memset(d,0,sizeof(d));
d[S]=1,q.push(S);
while(q.size()){
int x=q.front();q.pop();
for(int i=lin[x];i;i=Next[i]){
int y=ver[i];
if(!d[y]&&edge[i]){
d[y]=d[x]+1;q.push(y);
if(y==T) return 1;
}
}
}return 0;
}
int dinic(int x,int flow){
if(x==T) return flow;
int rest=flow;
for(int i=lin[x];i&&rest;i=Next[i]){
int y=ver[i];
if(d[y]==d[x]+1&&edge[i]){
int k=dinic(y,min(edge[i],rest));
if(!k) d[y]=0;
rest-=k,edge[i]-=k,edge[i^1]+=k;
if(!rest) return flow-rest;
}
}return flow-rest;
}
void tarjan(int x){
dfn[x]=low[x]=++num;ins[x]=1,s[++top]=x;
for(int i=lin[x];i;i=Next[i]){
int y=ver[i];
if(edge[i]&&!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}else if(ins[y]&&edge[i]) low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x]){
cnt++;int y;
do{
y=s[top--];c[y]=cnt;ins[y]=0;
}while(x!=y);
}
}
bool CMP(node a,node b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
int main(){
n=read(),m=read();
for(int i=1;i<=m;++i){
e[i].x=read(),e[i].y=read();
add(e[i].x,e[i].y);add(e[i].y,e[i].x);
}
for(int i=1;i<=n;++i) if(!color[i]) dfs(i,1);
S=0,T=n+1;tot=1;
memset(ver,0,sizeof(ver));
memset(lin,0,sizeof(lin));
memset(Next,0,sizeof(Next));
for(int i=1;i<=m;++i){
int x=e[i].x,y=e[i].y;
if(color[x]==2)Add(y,x,1);
else Add(x,y,1);
}
for(int i=1;i<=n;++i){
if(color[i]==1) Add(S,i,1);
else if(color[i]==2) Add(i,T,1);
}
while(bfs()){
while(flow=dinic(S,inf)) maxflow+=flow;
}
for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
int ans=0;
for(int i=2;i<=tot;i+=2){
int x=ver[i^1],y=ver[i];
if(x==0||y==0||x==T||y==T)continue;
if(edge[i]==0&&c[x]!=c[y])f[++ans].x=min(x,y),f[ans].y=max(x,y);
}
printf("%d\n",ans);
sort(f+1,f+ans+1,CMP);
for(int i=1;i<=ans;++i){
printf("%d %d\n",f[i].x,f[i].y);
}
return 0;
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 图像处理笔记(6)---- OpenCV waitKey函数
- SpringBoot整合Quartz作为调度中心完整实用例子
- SpringBoot整合SpringSecurity简单实现登入登出从零搭建
- SpringBoot整合SpringBatch实用简例
- 解决JPA懒加载典型的N+1问题-注解@NamedEntityGraph
- 基于Shiro,JWT实现微信小程序登录完整例子
- Spring Cloud Eureka 总结
- Spring Cloud Feign 总结
- 掘金15W沸点简单分析(一)
- SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建
- 基于AOP和ThreadLocal实现日志记录
- 搭建prometheus+grafana监控SpringBoot应用入门
- 掘金15W沸点简单分析(二)
- 老生常谈SpringAop日志收集与处理做的工具包
- 线程间通信wait---notify