hihocoder #1468 : 2-SAT·hihoCoder新春晚会 2-SAT

Posted tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihocoder #1468 : 2-SAT·hihoCoder新春晚会 2-SAT相关的知识,希望对你有一定的参考价值。

题目链接:

http://hihocoder.com/problemset/problem/1468

题意:

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

思路:

u和v不能同时出现,所以对应的边就是 u->(v的另一个),v->(u的另一个) 这两条,我们tarjan求出强联通分量,判断是否矛盾,如果r[i*2]==r[i*2-1]那么就矛盾,否则一定有解,因为要求字典序最小,所以我们编号从小的开始便利,如果这个节目上半场和下半场都没访问过,那么从上半场bfs[字典序的限制],得到一条符合规则的链,如果出现矛盾,也就是也访问过这条链上某个点对应的相反的点,那么就从当前节目的下半场bfs过去。 说的很迷,,看代码把 

代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 #define MS(a) memset(a,0,sizeof(a))
  5 #define MP make_pair
  6 #define PB push_back
  7 const int INF = 0x3f3f3f3f;
  8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
  9 inline ll read(){
 10     ll x=0,f=1;char ch=getchar();
 11     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
 12     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
 13     return x*f;
 14 }
 15 //////////////////////////////////////////////////////////////////////////
 16 const int maxn = 1e5+10;
 17 
 18 vector<int> g[maxn];
 19 
 20 void add(int u,int v){
 21     g[u].push_back(v);
 22 }
 23 
 24 int low[maxn],dfn[maxn],vis[maxn],ins[maxn],r[maxn],tot;
 25 stack<int> s;
 26 void tarjan(int u){
 27     low[u]=dfn[u] = ++tot;
 28     vis[u]=ins[u] = 1;
 29     s.push(u);
 30     for(int i=0; i<(int)g[u].size(); i++){
 31         int v = g[u][i];
 32         if(!vis[v]){
 33             tarjan(v);
 34             low[u] = min(low[u],low[v]);
 35         }else if(ins[v]){
 36             low[u] = min(low[u],dfn[v]);
 37         }
 38     }
 39 
 40     if(dfn[u] == low[u]){
 41         int t;
 42         do{
 43             t = s.top(); s.pop();
 44             r[t] = u;
 45             ins[t] = 0;
 46         }while(t != u);
 47     }
 48 }
 49 
 50 int tmp[maxn],ans[maxn];
 51 
 52 void bfs(int u){
 53     queue<int> q;
 54     q.push(u); vis[u] = 1;
 55     tmp[0] = 0;
 56     while(!q.empty()){
 57         int now = q.front(); q.pop();
 58         tmp[++tmp[0]] = now;
 59         for(int i=0; i<(int)g[now].size(); i++){
 60             int v = g[now][i];
 61             if(vis[v]) continue;
 62             vis[v] = 1;
 63             q.push(v);
 64         }
 65     }
 66 }
 67 
 68 bool judge(){
 69     for(int i=1; i<=tmp[0]; i++){
 70         if(vis[tmp[i]+(tmp[i]&1 ? 1 : -1)]) return false;
 71     }
 72     return true;
 73 }
 74 
 75 int main(){
 76     int n,m;
 77     cin >> n >> m;
 78     for(int i=0; i<m; i++){
 79         int u,v; scanf("%d%d",&u,&v);
 80         add(u,v+((v&1)?1:-1));
 81         add(v,u+((u&1)?1:-1));
 82     }
 83     for(int i=1; i<=2*n; i++){
 84         if(!dfn[i]) tarjan(i);
 85     }
 86 
 87     for(int i=1; i<2*n; i+=2){
 88         if(r[i] == r[i+1]){
 89             puts("NIE");
 90             return 0;
 91         }
 92     }
 93 
 94     MS(vis);
 95     for(int i=1; i<=n; i++){
 96         if(!vis[i*2] && !vis[i*2-1]){
 97             bfs(i*2-1);
 98             if(!judge()){
 99                 for(int j=1; j<=tmp[0]; j++) vis[tmp[j]] = 0;
100                 bfs(i*2);
101             }
102             for(int j=1; j<=tmp[0]; j++) ans[++ans[0]] = tmp[j];
103         }
104     }
105     sort(ans+1,ans+ans[0]+1);
106     for(int i=1; i<=n; i++){
107         cout << ans[i] << endl;
108     }
109 
110     return 0;
111 }

 

以上是关于hihocoder #1468 : 2-SAT·hihoCoder新春晚会 2-SAT的主要内容,如果未能解决你的问题,请参考以下文章

hihocoder #1467 : 2-SAT·hihoCoder音乐节 2-SAT

hiho一下第133周 2-SAT·hihoCoder音乐节(2-SAT)(强连通)

HihoCoder #1467 : 2-SAT·hihoCoder音乐节

HihoCoder 1638 : 小Hi的天平 (2-sat+并查集)

BZOJ 1468: Tree

[bzoj 1468] Tree