NOI2017 游戏 洛谷 P3825

本文深入探讨了2-SAT算法在解决特定问题中的应用,通过实例详细讲解了如何利用2-SAT算法进行建图与求解。文章首先介绍了问题背景,随后展示了算法的具体实现过程,包括预处理、Tarjan算法的应用以及最终解决方案的设计。此外,还分享了在实际编码过程中可能遇到的陷阱及应对策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://www.luogu.com.cn/problem/P3825

(NOI也不过如此,盲目自信.jpg

这题我们知道对于地图a,b,c来说,只有两种选择,那么就是2-sat裸题了,

考虑地图x,由于d<=8,我们让它要么是A,B要么是B,C,就包含所有情况了,只需要2^d的枚举

之前建图忘记对称建了,WA了一发,身败名裂.jpg

对称建也就是对于i要选择j,这个命题等于 选择 opp(j) 要选择 opp(i) 

#include<bits/stdc++.h>
using namespace std;

const int maxl=1e5+10;

int n,d,m,ind,top,ff;
int dfn[maxl],low[maxl],f[maxl],s[maxl];
int a[maxl][2],h[maxl][5];
char ch[maxl],tmp[3],out[maxl];
bool ansflag;
bool in[maxl],ans[maxl];
vector <int> xx,e[maxl];

inline void prework()
{
	scanf("%d%d",&n,&d);
	scanf("%s",ch+1);
	for(int i=1;i<=n;i++)
	{
		if(ch[i]=='x')
			xx.push_back(i);
		if(ch[i]=='a')
			a[i][0]=2,a[i][1]=3;
		if(ch[i]=='b')
			a[i][0]=1,a[i][1]=3;
		if(ch[i]=='c')
			a[i][0]=1,a[i][1]=2;
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&h[i][1]);
		scanf("%s",ch);h[i][2]=ch[0]-'A'+1;
		scanf("%d",&h[i][3]);
		scanf("%s",ch);h[i][4]=ch[0]-'A'+1;
	}
}

inline void tarjan(int u)
{
	dfn[u]=low[u]=++ind;
	in[u]=true;s[++top]=u;
	for(auto v : e[u])
	if(!dfn[v])
	{
		tarjan(v);
		low[u]=min(low[u],low[v]);
	}else if(in[v])
		low[u]=min(low[u],dfn[v]);
	if(dfn[u]==low[u])
	{
		ff++;int v;
		do
		{
			v=s[top--];
			f[v]=ff;in[v]=false;
		}while(u!=v);
	}
}

inline bool solv()
{
	ff=0;ind=0;top=0;
	for(int i=1;i<=2*n;i++)
	{
		dfn[i]=low[i]=f[i]=0;
		e[i].clear();in[i]=true;
	}
	int u,v;
	for(int i=1;i<=m;i++)
	{
		u=h[i][1];v=h[i][3];
		for(int j=0;j<=1;j++)
		if(h[i][2]==a[u][j])
		{
			if(h[i][4]!=a[v][0] && h[i][4]!=a[v][1])
				e[u+j*n].push_back(u+(1-j)*n);
			else if(h[i][4]==a[v][0])
			{
				e[u+j*n].push_back(v);
				e[v+n].push_back(u+(1-j)*n);
			}
			else 
			{
				e[u+j*n].push_back(v+n);
				e[v].push_back(u+(1-j)*n);
			}
		}
	}
	for(int i=1;i<=2*n;i++)
	if(!dfn[i])
		tarjan(i);
	for(int i=1;i<=n;i++)
	if(f[i]==f[i+n])
		return false;
	for(int i=1;i<=n;i++)
		ans[i]=f[i]>f[i+n];
	return true;
}

inline void dfs(int k)
{
	if(k==d)
	{
		if(solv())
		{
			ansflag=true;
			for(int i=1;i<=n;i++)
				out[i]=a[i][ans[i]]+'A'-1;
		}
		return;
	}
	a[xx[k]][0]=1;a[xx[k]][1]=2;
	dfs(k+1);
	if(ansflag) 
		return;
	a[xx[k]][0]=2;a[xx[k]][1]=3;
	dfs(k+1);
}

inline void mainwork()
{
	ansflag=false;
	dfs(0);
}

inline void print()
{
	if(!ansflag)
		printf("-1");
	else
		for(int i=1;i<=n;i++)
			printf("%c",out[i]);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

### 洛谷 P2303 题目解析与解决方案 洛谷 P2303 是一道经典的算法竞赛题目,涉及字符串处理和模拟操作。以下是关于该题目的详细解析与代码实现。 #### 题目描述 题目要求对一个字符串进行特定的字符替换操作,并输出最终结果。具体来说,需要根据输入的规则将某些字符替换为其他字符或数字,然后输出替换后的字符串。 #### 解决思路 1. **输入解析**:首先读取输入数据,包括原始字符串以及替换规则。 2. **规则存储**:使用一个映射(如数组或哈希表)来存储每个字符对应的替换值。 3. **字符串遍历**:逐一遍历原始字符串中的每个字符,根据映射关系将其替换为指定值。 4. **输出结果**:将替换后的字符串输出。 以下是一个基于 C++ 的实现方案: ```cpp #include <iostream> #include <string> using namespace std; int main() { string s; cin >> s; // 输入原始字符串 int n; cin >> n; // 替换规则的数量 // 创建映射表,初始值为自身 char map[256]; for (int i = 0; i < 256; i++) { map[i] = i; } // 处理替换规则 for (int i = 0; i < n; i++) { char from, to; cin >> from >> to; map[from] = to; // 更新映射关系 } // 替换字符串中的字符 for (int i = 0; i < s.length(); i++) { s[i] = map[s[i]]; // 根据映射表替换字符 } cout << s << endl; // 输出替换后的字符串 return 0; } ``` #### 关键点解析 - **映射表设计**:通过 `map` 数组记录每个字符的替换规则。如果某个字符没有被显式替换,则保持其原始值[^6]。 - **时间复杂度**:字符串遍历的时间复杂度为 \(O(m)\),其中 \(m\) 为字符串长度;处理替换规则的时间复杂度为 \(O(n)\),其中 \(n\) 为规则数量。总体复杂度为 \(O(m + n)\)[^7]。 - **空间复杂度**:映射表占用固定大小的空间(256 字节),因此空间复杂度为 \(O(1)\)[^8]。 #### 示例输入输出 **输入示例**: ``` abcde 3 a 1 b 2 e ! ``` **输出示例**: ``` 12cd! ``` --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值