【XVII Open Cup E.V. Pankratiev. Grand Prix of Europe. L】Lost Logic 題解

題目大意

  有 nn 個布爾變量 x1,,xnx_1,\cdots,x_n,在一組約束下恰好有三種賦值方式。
  約束是形如 xixjx_i \to x_j 這樣,xix_i 可以是 !xi!x_ixjx_j 可以是 !xj!x_j
  現給出這三種賦值方式,請構造出一組約束。

  n50n \leq 50,你構造的約束數量 500\leq 500

\\
\\
\\

題解

  紀念一下已經傻掉的自己

  因爲這個題目模型很 2-sat,所以上來就在想 tarjan,沒想到最後居然是這麼 sb 的做法。。

  首先,如果一個變量在三次賦值中都是相同的,那它是常值變量,可以一條約束直接解決掉。(若 xi0x_i \equiv 0,則 !xixi!x_i \to x_i;若 xi1x_i \equiv 1,則 xi!xix_i \to !x_i
  然後,合併本質相同的變量。即,若 xix_ixjx_j 取值完全相同或完全相反,都可以用兩條約束解決掉。

  那麼,最後一定只能剩下兩個變量。
  這是因爲,由於合併了本質相同的變量,因此本質不同的情況最多隻有 4 種,而其中有一種是常值的情況,因此最多隻有 3 種。但是如果有 3 種的話,是無解的,因此最多 2 種。而合法的數據又不會只有 1 種,因此只能是 2 種。

  剩下的這兩個變量可以一條約束解決掉。

  所以最後在 2n2n 條約束下就解決了。

代碼

#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

typedef long long LL;

const int maxn=1e5+5;

int n,a[maxn][4],m;
pair<pair<int,int>,pair<int,int>> ans[maxn];

int main()
{
	scanf("%d",&n);
	fo(j,1,3)
		fo(i,1,n) scanf("%d",&a[i][j]);
	
	int cnt=0, w1, w2;
	fo(i,1,n) if (a[i][1]==a[i][2] && a[i][1]==a[i][3])
	{
		ans[++m]=make_pair(make_pair(i,a[i][1]),make_pair(i,a[i][1]^1));
	} else
	{
		bool idp=1;
		fo(j,1,i-1) if (a[i][1]==a[j][1] && a[i][2]==a[j][2] && a[i][3]==a[j][3])
		{
			idp=0;
			ans[++m]=make_pair(make_pair(j,0),make_pair(i,0));
			ans[++m]=make_pair(make_pair(j,1),make_pair(i,1));
			break;
		} else if (a[i][1]!=a[j][1] && a[i][2]!=a[j][2] && a[i][3]!=a[j][3])
		{
			idp=0;
			ans[++m]=make_pair(make_pair(j,0),make_pair(i,1));
			ans[++m]=make_pair(make_pair(j,1),make_pair(i,0));
			break;
		}
		if (idp)
		{
			++cnt;
			if (cnt==1) w1=i; else w2=i;
		}
	}
	
	if (cnt!=2) puts("-1"); else
	{
		int df;
		if (a[w1][1]!=a[w1][2] && a[w1][1]!=a[w1][3]) df=1;
			else if (a[w1][2]!=a[w1][1] && a[w1][2]!=a[w1][3]) df=2;
				else df=3;
		ans[++m]=make_pair(make_pair(w1,a[w1][df]^1),make_pair(w2,a[w2][df]^1));
		
		printf("%d\n",m);
		fo(i,1,m)
		{
			if (ans[i].first.second) putchar('!');
			printf("x%d -> ",ans[i].first.first);
			if (ans[i].second.second) putchar('!');
			printf("x%d\n",ans[i].second.first);
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章