hihoCoder #1468 : 2-SAT·hihoCoder新春晚会(2-SAT 输出字典序最小的方案)
生活随笔
收集整理的這篇文章主要介紹了
hihoCoder #1468 : 2-SAT·hihoCoder新春晚会(2-SAT 输出字典序最小的方案)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
描述
hihoCoder新春晚會正在緊張地籌備中。晚會分為上半場和下半場,總導演小Hi現在要為N個節目安排演出時間(上半場或下半場)。為了描述方便,我們將第i個節目對應兩個編號2i-1和2i,分別表示把第i個節目安排在上半場和下半場。
由于演員、道具和布景的限制。有些安排之間存在沖突,比如編號1的安排和編號4的安排有沖突,意味著"把第1個節目安排在上半場"同"把第2個節目安排在下半場"有沖突。
現在小Hi手里有M對編號,表示沖突的節目安排。他的任務是幫助主辦方安排出節目演出的合理時間。
輸入
第一行包含兩個非負整數n和m(n≤8000,m≤20000),代表有n個節目和m對沖突。
接下來m行每行兩個數x和y,表示編號x和編號y沖突。
輸出
輸出n行,每行一個數,從小到大輸出最后進行演出的編號。若有多解,則輸出字典序最小的。無解則輸出NIE。
樣例輸入
3 2
1 3
2 4
樣例輸出
1
4
5
思路
SAT建邊,然后暴力DFS(NMNMNM)
每個點拆成了兩個點i1和i2i_1 和i_2i1?和i2?
先從最小的點i1i_1i1?開始枚舉將路徑上的點標記,如果存在矛盾那么這個點不符合,然后枚舉i2i_2i2?,如果這個點還存在矛盾,那么無解
建圖的時候要對應好關系,對于這個題i1和i2i_1 和i_2i1?和i2?是互斥的,所以要 (i1→?i2ori2→?i1i_1 \to\lnot i_2or i_2\to\lnot i_1i1?→?i2?ori2?→?i1?) 而不是(?i1→i2or?i2→i1\lnot i_1 \to i_2or \lnot i_2\to i_1?i1?→i2?or?i2?→i1?)
#include <bits/stdc++.h> #define LL long long #define P pair<int, int> #include <time.h> #define lowbit(x) (x & -x) #define mem(a, b) memset(a, b, sizeof(a)) #define rep(i, a, n) for (int i = a; i <= n; ++i) const int maxn = 1044373; #define mid ((l + r) >> 1) #define lc rt<<1 #define rc rt<<1|1 using namespace std;int read() {int num = 0, flag = 1;char c = getchar();while (c < '0' || c > '9') flag = (c == '-') ? -1 : 1, c = getchar();while (c >= '0' && c <= '9') num = (num << 3) + (num << 1) + c - '0', c = getchar();return num * flag; } void out(int x) {if (x > 9) out(x / 10);putchar(x % 10 + '0'); }vector<int> g[maxn]; int tmp[maxn], vis[maxn], len;int other(int x) {if (x & 1) return x+1;else return x-1; }int dfs(int x) {if (vis[other(x)]) return 0;if (vis[x]) return 1;tmp[len++] = x;vis[x] = 1;for (int i = 0, y; i < (int)g[x].size(); ++i) {y = g[x][i];if (dfs(y) == 0) return 0;}return 1; }int main() {ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);int n, m;scanf("%d %d", &n, &m);for (int i = 0, l, r; i < m; ++i) {scanf("%d %d", &l, &r);g[l].push_back(other(r));g[r].push_back(other(l));}for (int i = 1; i <= n; ++i) {if (vis[i*2] || vis[i*2-1]) continue;len = 0;if (dfs(i*2-1) == 0) {for (int j = 0; j < len; ++j) {vis[tmp[j]] = 0;}len = 0;if (dfs(i*2) == 0) {puts("NIE");return 0;}}}for (int i = 1; i <= n*2; ++i) if (vis[i]) printf("%d\n", i);return 0; }總結
以上是生活随笔為你收集整理的hihoCoder #1468 : 2-SAT·hihoCoder新春晚会(2-SAT 输出字典序最小的方案)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU-6470 Count (构造矩阵
- 下一篇: 2-SAT