tarjan/2-sat

tarjan求割点板子

#include <bits/stdc++.h>
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
#define Fanv(x) for(int i=edge::sum[x-1]+1,now_v=edge::e[i].y;i<=edge::sum[x];i++,now_v=edge::e[i].y)  //For_all_neighbor_vertex 枚举x的所有邻居,now_v=当前枚举的邻居 
const int N=100000,M=200000,type=0;//点数,边数最大值(开空间用),有向图type=0,无向图为1
using namespace std;
namespace Fast_IO {
	int read() {
		int x(0);
		char ch(getchar());
		while(ch>'9'||ch<'0')ch=getchar();
		while(ch<='9'&&ch>='0') {
			x=x*10+ch-'0';
			ch=getchar();
		}
		return x;
	}
}
namespace edge {
	int n,m,sum[N+1],cnt(0);
	struct element {
		int x,y,len;//边的起点,终点,边权
		bool operator < (const element a)const {
			if(x!=a.x)return x<a.x;
			else return y<a.y;
		}
	} e[(1+type)*M+1];
	inline void add_edge(int st,int en,int val) {
		e[++cnt].x=st;
		e[cnt].y=en;
		e[cnt].len=val;
	}
	void work() {
		e[0].x=e[0].y=0;
		sum[0]=0;
		std::sort(e+1,e+cnt+1);
		for(int i=1; i<=cnt; i++) {
			if(e[i].x!=e[i+1].x) {
				sum[e[i].x]=i;
			}
		}
		for(int i=1; i<=n; i++)sum[i]=max(sum[i],sum[i-1]);
	}
	void reset() {
		cnt=0;
	}
}
namespace Tarjan {
	int dfn[N+1],low[N+1],col[N+1],s[N+1],b[N+1],cnt(0),cnt_col(0),cnt_sta(0);
	int cut[N+1];
	void dfs(int now,int fa) {
		dfn[now]=low[now]=++cnt;
		s[++cnt_sta]=now;
		b[now]=1;
		cut[now]=0;
		int num_child(0);
		Fanv(now) {
			if(now_v!=fa) {
				if(!dfn[now_v]) {
					dfs(now_v,now);
					low[now]=min(low[now],low[now_v]);
					if(low[now_v]>=dfn[now]&&fa)cut[now]=1;
					++num_child;
				}
				low[now]=min(low[now],dfn[now_v]);
			}
		}
		if(dfn[now]==low[now]) {
			int now_col=++cnt_col;
			while(s[cnt_sta]!=now) {
				col[s[cnt_sta]]=now_col;
				b[s[cnt_sta]]=0;
				--cnt_sta;
			}
			col[s[cnt_sta]]=now_col;
			b[s[cnt_sta]]=0;
			--cnt_sta;
		}
		if(fa==0&&num_child>=2)cut[now]=1;
	}
	void work() {
		for(int i=1; i<=edge::n; i++) {
			if(!dfn[i])dfs(i,0);
		}
	}
}
int main() {
//	freopen("P3388_1.in","r",stdin);
//	freopen("1.out","w",stdout);
	edge::n=Fast_IO::read();
	edge::m=Fast_IO::read();
	for(int i=1; i<=edge::m; i++) {
		int x,y,len;
		x=Fast_IO::read();
		y=Fast_IO::read();
//		len=Fast_IO::read();
		edge::add_edge(x,y,len);
		edge::add_edge(y,x,len);
	}
	edge::work();
	Tarjan::work();
	int ans(0);
	for(int i=1; i<=edge::n; i++) {
		ans+=Tarjan::cut[i];
	}
	cout<<ans<<endl;
	for(int i=1; i<=edge::n; i++) {
		if(Tarjan::cut[i])cout<<i<<" ";
	}
	return 0;
}

2-sat板子

#include <bits/stdc++.h>
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
#define Fanv(x) for(int i=edge::sum[x-1]+1,now_v=edge::e[i].y;i<=edge::sum[x];i++,now_v=edge::e[i].y)  //For_all_neighbor_vertex 枚举x的所有邻居,now_v=当前枚举的邻居 
const int N=2000000,M=2000000;//点数,边数最大值(开空间用),有向图type=0,无向图为1
using namespace std;
namespace Fast_IO {
	int read() {
		int x(0);
		char ch(getchar());
		while(ch>'9'||ch<'0')ch=getchar();
		while(ch<='9'&&ch>='0') {
			x=x*10+ch-'0';
			ch=getchar();
		}
		return x;
	}
}
namespace edge {
	int n,m,sum[N+1],cnt(0);
	struct element {
		int x,y,len;//边的起点,终点,边权
		bool operator < (const element a)const {
			if(x!=a.x)return x<a.x;
			else return y<a.y;
		}
	} e[M+1];
	inline void add_edge(int st,int en,int val) {
		e[++cnt].x=st;
		e[cnt].y=en;
		e[cnt].len=val;
	}
	void work() {
		e[0].x=e[0].y=0;
		sum[0]=0;
		std::sort(e+1,e+cnt+1);
		for(int i=1; i<=cnt; i++) {
			if(e[i].x!=e[i+1].x) {
				sum[e[i].x]=i;
			}
		}
		for(int i=1; i<=n; i++)sum[i]=max(sum[i],sum[i-1]);
	}
	void reset() {
		cnt=0;
	}
}
namespace Tarjan {
	int dfn[N+1],low[N+1],col[N+1],s[N+1],b[N+1],cnt(0),cnt_col(0),cnt_sta(0);
//	int cut[N+1];
	void dfs(int now,int fa) {
		dfn[now]=low[now]=++cnt;
		s[++cnt_sta]=now;
		b[now]=1;
//		cut[now]=0;
		int num_child(0);
		Fanv(now) {
			if(now_v!=fa) {
				if(!dfn[now_v]) {
					dfs(now_v,now);
					low[now]=min(low[now],low[now_v]);
//					if(low[now_v]>=dfn[now]&&fa)cut[now]=1;
					++num_child;
				}
				else if(b[now_v])low[now]=min(low[now],dfn[now_v]);
			}
		}
		if(dfn[now]==low[now]) {
			++cnt_col;
			while(s[cnt_sta]!=now) {
				col[s[cnt_sta]]=cnt_col;
				b[s[cnt_sta]]=0;
				--cnt_sta;
			}
			col[s[cnt_sta]]=cnt_col;
			b[s[cnt_sta]]=0;
			--cnt_sta;
		}
//		if(fa==0&&num_child>=2)cut[now]=1;
	}
	void work() {
		memset(dfn,0,sizeof(dfn));
		for(int i=1; i<=edge::n; i++) {
			if(!dfn[i])dfs(i,0);
		}
	}
}
int main() {
//	freopen("P3388_1.in","r",stdin);
//	freopen("1.out","w",stdout);
	edge::n=2*Fast_IO::read();
	edge::m=2*Fast_IO::read();
	for(int i=1; i<=edge::m/2; i++) {
		int x,y,a,b;
		x=Fast_IO::read();
		a=Fast_IO::read();
		y=Fast_IO::read();
		b=Fast_IO::read();
//		len=Fast_IO::read();
		edge::add_edge(x+(1-a)*edge::n/2,y+b*edge::n/2,0);
		edge::add_edge(y+(1-b)*edge::n/2,x+a*edge::n/2,0);
	}
	edge::work();
	Tarjan::work();
	for(int i=1; i<=edge::n/2; i++)if(Tarjan::col[i]==Tarjan::col[i+edge::n/2]) {
			cout<<"IMPOSSIBLE"<<endl;
			return 0;
		}
	cout<<"POSSIBLE"<<endl;	
	for(int i=1; i<=edge::n/2; i++) {
			cout<<(Tarjan::col[i]>Tarjan::col[i+edge::n/2])<<" ";
		}
	return 0;
}
posted @ 2022-04-29 17:18  永无岛  阅读(40)  评论(0编辑  收藏  举报