1. 程式人生 > >hihocoder #1468 : 2-SAT·hihoCoder新春晚會 2-SAT

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

color http getc 對沖 bool lan log ons 主辦方

題目鏈接:

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