您的位置:首页 > 其它

Ligthoj 1407 Explosion

2015-10-06 21:09 330 查看
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1407

题目大意:

有一个机器产生m个限制,限制有4种:

1. x or y 至少有1个人参加

2. x不参加 则 y必须不参加,(隐含 y参加 x必须参加

3. x or y 至少有1个人不参加

4. x & y 同时参加 或者不参加

有 k 个人 进行投票,有2种类别

1. x y z 至少有一个人参加

2. x y z 至少有一个人不参加

有n 个人参加会议,m 个机器限制,k个人投票 (3 ≤ n ≤ 1000, 0 ≤ m ≤ 2000, 0 ≤ k ≤ 5)

解题思路:肯定是 2-sat,k比较小直接枚举3^k。剩下的就是一个模板。

纪念一下我写的第二个2-sat的题目。

//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#include<time.h>
#include<stdlib.h>
#include<ctype.h>
#include<list>
//#include<ext/rope>
#define PB push_back
#define MP make_pair
#define PF push_front
#define lson k<<1
#define rson k<<1|1
using namespace std;
typedef long long ll;
typedef double db;
typedef long double ldb;

const int N = 1005;

/// from 0 to n-1
struct TwoSat
{
int n;
vector<int> link[N << 1];
bool mk[N << 1];
int ch[5][4], stk
, top; /// the size of stk is N or N*2 ???
int k, a[5];
void setmk()
{
for(int i = 0; i < n << 1; i++) mk[i] = false;
}
void init(int n, int k)
{
this->n = n;
this->k = k;
for(int i = 0; i < n << 1; i++) link[i].clear();
setmk();
}
void add(int op, int x, int y)
{
if(op == 1) link[x << 1 | 1].PB(y << 1), link[y << 1 | 1].PB(x << 1);
else if(op == 2) link[x << 1 | 1].PB(y << 1 | 1), link[y << 1].PB(x << 1);
else if(op == 3) link[x << 1].PB(y << 1 | 1), link[y << 1].PB(x << 1 | 1);
else
{
link[x << 1 | 1].PB(y << 1), link[y << 1 | 1].PB(x << 1);
link[x << 1].PB(y << 1 | 1), link[y << 1].PB(x << 1 | 1);
}
}
bool dfs(int x)
{
if(mk[x ^ 1]) return false;
if(mk[x]) return true;
mk[x] = true;
stk[++top] = x;
for(int i = 0; i < link[x].size(); i++)
if(!dfs(link[x][i])) return false;
return true;
}
bool solve()
{
for(int i = 0; i < n << 1; i += 2)
{
if(!mk[i] && !mk[i + 1])
{
top = 0;
if(!dfs(i))
{
while(top) mk[stk[top--]] = false;
if(!dfs(i + 1)) return false;
}
}
}
return true;
}
void input(int j)
{
for(int i = 0; i < 4; i++) scanf("%d", &ch[j][i]);
}
bool work(int p)
{
if(p == k)
{
setmk();
for(int i = 0; i < k; i++)
{
int t = abs(a[i]) << 1;
t -= 2;
if(a[i] < 0) ++t;
top = 0;
if(!dfs(t)) return false;
}
if(solve()) return true;
return false;
}
else
{
for(int i = 1; i < 4; i++)
{
if(ch[p][0] == 1) a[p] = ch[p][i];
else a[p] = -ch[p][i];
if(work(p + 1)) return true;
}
return false;
}
}
void output()
{
int cnt(0);
for(int i = 0; i < n << 1; i += 2) if(mk[i]) cnt++;
printf(" %d", cnt);
for(int i = 0; i < n << 1; i += 2) if(mk[i]) printf(" %d", (i >> 1) + 1);
}
} st;

int main()
{
#ifdef PKWV
//    freopen("in.in", "r", stdin);
#endif // PKWV
int T, cas(1);
scanf("%d", &T);
while(T--)
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
st.init(n, k);
for(int i = 0; i < m; i++)
{
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
x--, y--;
st.add(op, x, y);
}
for(int i = 0; i < k; i++) st.input(i);
printf("Case %d: ", cas++);
if(st.work(0))
{
printf("Possible");
st.output();
printf(".\n");
}
else printf("Impossible.\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: