51nod 1318 最大公约数与最小公倍数方程组(2-SAT)

一道2-SAT好题。
题目
题解

用map建边。几乎1 A。
说明细节想清楚在复杂的题也是不难写的。一定要在写之前想清楚,不要想着写完再想

#include<bits/stdc++.h>
using namespace std;
#define maxn 1020
#define N 100020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define prev prev_
#define stack stack_
#define inf 0x3f3f3f3f

typedef long long ll;

struct node{
	int tp,x,y,c;
}dt[maxn];
struct node2{
	int next,to;
}e[N * 10];
int head[N],cnt,sol[N],bcnt,low[N],dfn[N],belong[N],ins[N];
int s[N],tops,dfstime;
map <int,int> num,tag;
map <int,int>::iterator it;
map <int,int> mx[maxn];
map <pair<int,int>,int> rec[maxn];
vector <pair<int,int> > vec[N];
vector <int> c[N];

int tot,tot2;
int n,m,T;
int prime[N],tag2[N],cnt2;

void clear(){
	rep(i,1,n){
		mx[i].clear() , rec[i].clear();
	}
	rep(i,1,tot2 * 2) c[i].clear() , dfn[i] = head[i] = 0;
	tops = dfstime = bcnt = cnt = tot2 = 0;
}
void pre(){
	rep(i,2,100000){
		if ( !tag2[i] ) prime[++cnt2] = i;
		for (register int j = 1 ; j <= cnt2 && prime[j] * i <= 100000 ; j++){
			tag2[i * prime[j]] = 1;
			if ( i % prime[j] == 0 ) break;
		}
	}
}
void factor(int x){
	if ( num[x] ) return;
	num[x] = ++tot;
	rep(i,1,x){
		if ( prime[i] * prime[i] > x ) break;
		if ( x % prime[i] == 0 ){
			int c = 0;
			while ( x % prime[i] == 0 ) c++ , x /= prime[i];
			vec[tot].pb(mp(prime[i],c));
		}
	}
	if ( x > 1 ) vec[tot].pb(mp(x,1));
}
inline void adde(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
void force_not(int x){
	for (it = mx[x].begin() ; it != mx[x].end() ; ++it){
		pair <int,int> cur = *it;
		cur.se = 1;
		if ( !tag[cur.fi] ){
			adde(rec[x][cur] + tot2,rec[x][cur]); // force not choose
		}
	}
}
void force_not(int x,int y){
	for (it = mx[x].begin() ; it != mx[x].end() ; ++it){
		pair <int,int> cur = *it;
		cur.se = 1;
		if ( tag[cur.fi] || !rec[y][cur] ) continue;
		adde(rec[x][cur] + tot2,rec[y][cur]); // if x , force not choose y
	}
}

void init(){
	rep(i,1,n){
	//	cout<<i<<endl;
		for (it = mx[i].begin() ; it != mx[i].end() ; ++it){
			pair <int,int> cur = *it;
		//	cout<<cur.fi<<" "<<cur.se<<endl;
			while ( cur.se ){
				rec[i][cur] = ++tot2;
				cur.se--;
			}
			
		}
	}
	//tot2 + i : 1 ( 选了 )
	//i : 0  ( 不选 )
	rep(i,1,n){
		for (it = mx[i].begin() ; it != mx[i].end() ; ++it){
			pair <int,int> cur,cur2 = *it; cur = cur2;
			cur.se--;
			while ( cur.se ){
			   	adde(rec[i][cur2] + tot2,rec[i][cur] + tot2);
				adde(rec[i][cur],rec[i][cur2]);
				cur.se-- , cur2.se--;
			}
		}
	}
	rep(i,1,m){
		int tp = dt[i].tp , x = dt[i].x , y = dt[i].y , c = dt[i].c;
		pair<int,int> cur; tag.clear();
		if ( tp == 1 ){ //LCM
			rvc(j,vec[c]){
				cur = vec[c][j];
				adde(rec[x][cur],rec[y][cur] + tot2);
				adde(rec[y][cur],rec[x][cur] + tot2);
				tag[cur.fi] = 1 , cur.se++;
				adde(rec[x][cur] + tot2,rec[x][cur]);
				adde(rec[y][cur] + tot2,rec[y][cur]);
			}
			force_not(x);
			force_not(y);
		}
		else{ //GCD
			rvc(j,vec[c]){
				cur = vec[c][j] , tag[cur.fi] = 1;
				adde(rec[x][cur],rec[x][cur] + tot2);
				adde(rec[y][cur],rec[y][cur] + tot2);
				cur.se++;
				adde(rec[x][cur] + tot2,rec[y][cur]);
				adde(rec[y][cur] + tot2,rec[x][cur]);
			}
			force_not(x,y);
			force_not(y,x);
		}
	}
}
void dfs(int x){
	low[x] = dfn[x] = ++dfstime;
	s[++tops] = x , ins[x] = 1;
	fore(i,x){
		if ( !dfn[e[i].to] ) dfs(e[i].to) , low[x] = min(low[x],low[e[i].to]);
		else if ( ins[e[i].to] ) low[x] = min(low[x],low[e[i].to]);
	}
	if ( dfn[x] == low[x] ){
		int cur = s[tops--]; ++bcnt;
		while ( cur != x ){
			ins[cur] = 0 , belong[cur] = bcnt;
			c[bcnt].pb(cur);
			cur = s[tops--];
		}
		ins[cur] = 0 , belong[cur] = bcnt;
		c[bcnt].pb(cur);
	}
}
inline int get_v(int n,int x){
	int r = x > n ? x - n : x;
	if ( sol[r] == -1 ) return -1;
	return x > n ? !sol[r] : sol[r];
}
bool two_SAT(int n){
	rep(i,1,n) sol[i] = -1;
	rep(i,1,n * 2) if ( !dfn[i] ) dfs(i);
	rep(i,1,n){
		if ( belong[i] == belong[i + n] ) return 0;
	}
/*	rep(i,1,bcnt){
		int val = 1;
		rvc(j,c[i]){
			int cur = c[i][j];
			if ( get_v(n,cur) == 0 ) val = 0;
			fore(k,cur){
				if ( get_v(n,e[k].to) == 0 ) val = 0;
			}
			if ( !val ) break;
		}
		rvc(j,c[i]){
			if ( c[i][j] > n ) sol[c[i][j] - n] = !val;
			else sol[c[i][j]] = val;
		}
	}*/
	return 1;
}
int main(){
	freopen("input.txt","r",stdin);
	pre();
	scanf("%d",&T);
	rep(t,1,T){
		clear();
		scanf("%d %d",&n,&m);
		rep(i,1,m){
			char s[10]; int x,y,c,cur;
			scanf("%s %d %d %d",s,&x,&y,&c) , x++ , y++;
			factor(c) , cur = num[c];
			rvc(j,vec[cur]){
				mx[x][vec[cur][j].fi] = max(mx[x][vec[cur][j].fi],vec[cur][j].se);
				mx[y][vec[cur][j].fi] = max(mx[y][vec[cur][j].fi],vec[cur][j].se);
			}
			if ( s[0] == 'L' ){
				dt[i] = (node){1,x,y,cur};	
			}
			else{
				dt[i] = (node){2,x,y,cur};
			}
		}
		init();
		if ( two_SAT(tot2) ) cout<<"Solution exists\n";
		else cout<<"Solution does not exist\n";
	}
}


猜你喜欢

转载自blog.csdn.net/weixin_42484877/article/details/82843502