题目来源:Light OJ 1251 Forming the Council
题意:若干了条件至少满足一个 求是否有方案 输出任意一种可能的方案 留下的人的个数
思路:2-SAT基础题
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 100010;
int n, m;
vector <int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2], c;
int a[maxn], b[maxn], sum;
int ans[maxn];
bool dfs(int x)
{
if(mark[x^1])
return false;
if(mark[x])
return true;
mark[x] = true;
S[c++] = x;
for(int i = 0; i < G[x].size(); i++)
if(!dfs(G[x][i]))
return false;
return true;
}
void init()
{
for(int i = 0; i < n*2; i++)
G[i].clear();
memset(mark, 0, sizeof(mark));
}
void AddEdge(int u, int v, int x, int y)
{
u = u * 2 + x;
v = v * 2 + y;
G[u].push_back(v^1);
G[v].push_back(u^1);
}
bool solve()
{
for(int i = 0; i < n*2; i += 2)
{
if(!mark[i] && !mark[i+1])
{
c = 0;
if(!dfs(i))
{
while(c > 0)
mark[S[--c]] = false;
if(!dfs(i+1))
return false;
}
}
}
return true;
}
int get(char *s)
{
int ans = 0;
for(int i = 1; s[i]; i++)
ans = ans * 10 + s[i] - '0';
return ans;
}
int main()
{
int cas = 1;
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d %d", &m, &n);
init();
while(m--)
{
char s1[100], s2[100];
scanf("%s %s", s1, s2);
int u = get(s1);
int v = get(s2);
u--;
v--;
int x, y;
if(s1[0] == '+')
x = 1;
else
x = 0;
if(s2[0] == '+')
y = 1;
else
y = 0;
AddEdge(u, v, x^1, y^1);
}
if(!solve())
{
printf("Case %d: No\n", cas++);
continue;
}
int l = 0;
for(int i = 0; i < n; i++)
if(mark[i*2+1])
ans[l++] = i;
printf("Case %d: Yes\n", cas++);
printf("%d", l);
for(int i = 0; i < l; i++)
printf(" %d", ans[i]+1);
puts("");
}
return 0;
}