[HAOI2017]新型城市化 二分图+网络流+关键割边

[HAOI2017]

  • 就是求二分图的关键边
  • 一条边是二分图的关键边当且仅当:这条边满流&&边的两端不在一个scc中
  • 一条边是二分图的可行边当且仅当:这条边满流||边的两端在一个scc中
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int inf=1e9;
const int N=2e4;
const int M=2e5;
struct node{int x,y,v,n,id;}e[M<<1],E[M<<1];
struct QWQ{int x,y;}q[M],ans[M];
int lin[M<<1],LIN[M<<1],dfn[N],low[N],inv[N],c[N],d[N],v[M<<1],scc,tot,S,T,LEN,len=1,n,m,x,y;
inline int read(){
	int num=0;char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))num=num*10+ch-'0',ch=getchar();
	return num;
}
inline void Print(int x){if(x>9)Print(x/10);putchar(x%10+'0');}

void LK(int x,int y,int v,node *e,int *lin,int &len){
	e[++len].y=y,e[len].x=x,e[len].v=v,e[len].n=lin[x],lin[x]=len;
}
void add(int x,int y,int v){
	LK(x,y,v,e,lin,len),LK(y,x,0,e,lin,len);
}
void DFS(int x){
	for(int i=LIN[x];i;i=E[i].n){
		int y=E[i].y;
		if(v[y]!=-1)continue;
		v[y]=v[x]^1;DFS(y);
	}
}
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=e[i].n){
			int y=e[i].y;
			if(d[y]||!e[i].v)continue;
			d[y]=d[x]+1;q.push(y);
		}
	}return d[T]>0;
}
int dfs(int x,int minf){
	if(x==T)return minf;
	int flow=0,sum=0;
	for(int i=lin[x];i;i=e[i].n){
		int y=e[i].y;
		if(d[y]!=d[x]+1||!e[i].v)continue;
		flow=dfs(y,min(minf,e[i].v));
		if(!flow)d[y]=0;
		sum+=flow,minf-=flow,e[i].v-=flow,e[i^1].v+=flow;
		if(!minf)return sum;
	}return sum;
}
stack<int> SS;
void tarjan(int x){
	dfn[x]=low[x]=++tot;inv[x]=1;SS.push(x);
	for(int i=lin[x];i;i=e[i].n){
		int y=e[i].y;
		if(!e[i].v)continue;
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}else if(inv[y]) low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x]){
		int now=-1;scc++;
		while(now!=x){
			now=SS.top();SS.pop();
			c[now]=scc;
			inv[now]=0;
		}
	}
}
bool cmp(QWQ a,QWQ b){return a.x==b.x&&a.y<b.y||a.x<b.x;}
int main()
{
	//freopen("a.in","r",stdin);
	n=read(),m=read(); S=0,T=n+1;
	rep(i,1,m){
		x=read(),y=read();
		q[i].x=x,q[i].y=y;
		LK(x,y,0,E,LIN,LEN),LK(y,x,0,E,LIN,LEN);
	}
	memset(v,-1,sizeof(v));
	rep(i,1,n)if(v[i]==-1)v[i]=0,DFS(i);
	rep(i,1,m){
		x=q[i].x,y=q[i].y;
		if(v[x])add(y,x,1);
		else add(x,y,1);
	}
	rep(i,1,n){
		if(v[i])add(i,T,1);
		else add(S,i,1);
	}
	while(bfs())dfs(S,inf);
	rep(i,1,n)if(!dfn[i])tarjan(i);
	tot=0;
	for(int i=2;i<=len;i+=2){
		x=e[i].x,y=e[i].y;
		if(x==0||y==0||x==T||y==T)continue;
		if(e[i].v==0&&c[x]!=c[y])ans[++tot].x=min(x,y),ans[tot].y=max(x,y);
	}
	cout<<tot<<"\n";
	sort(ans+1,ans+tot+1,cmp);
	rep(i,1,tot)cout<<ans[i].x<<" "<<ans[i].y<<"\n";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/strangeDDDF/article/details/88765217