当前位置: 代码迷 >> 综合 >> POJ 3683 2-sat 输出解
  详细解决方案

POJ 3683 2-sat 输出解

热度:21   发布时间:2024-01-13 17:56:45.0

题意方法和之前的3648基本一样

注意输出解的方式,分成两部分的点集,应该遍历其中一个点集,根据染色判断选择该点集的点还是另一个点集的点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#define MAXN 5005
#define MAXM 50005
#define INF 1000000000
using namespace std;
int start[MAXN], end[MAXN], last[MAXN];
int n, index, scc;
vector<int>g[MAXN], dag[MAXN];
int dfn[MAXN], low[MAXN], instack[MAXN];
int fa[MAXN], ha[MAXN], color[MAXN], ind[MAXN];
queue<int>q;
stack<int>st;
void init()
{index = scc = 0;memset(instack, 0, sizeof(instack));for(int i = 0; i < MAXN; i++) g[i].clear(), dag[i].clear();memset(dfn, 0, sizeof(dfn));memset(color, 0, sizeof(color));memset(ind, 0, sizeof(ind));memset(ha, 0, sizeof(ha));while(!q.empty()) q.pop();while(!st.empty()) st.pop();
}
bool conflict(int lx, int ly, int rx, int ry)
{if(lx >= rx && lx <= ry) return true;if(ly >= rx && ly <= ry) return true;if(rx >= lx && rx <= ly) return true;if(ry >= lx && ry <= ly) return true;return false;
}
void build()
{for(int i = 1; i <= n; i++)for(int j = i + 1; j <= n; j++){if(conflict(start[i], start[i] + last[i] - 1, start[j], start[j] + last[j] - 1)) g[i].push_back(j + n), g[j].push_back(i + n);if(conflict(start[i], start[i] + last[i] - 1, end[j] - last[j] , end[j] - 1)) g[i].push_back(j), g[j + n].push_back(i + n);if(conflict(end[i] - last[i], end[i] - 1, start[j], start[j] + last[j] - 1)) g[i + n].push_back(j + n), g[j].push_back(i);if(conflict(end[i] - last[i], end[i] - 1, end[j] - last[j] , end[j] - 1)) g[i + n].push_back(j), g[j + n].push_back(i);}
}
void tarjan(int u)
{dfn[u] = low[u] = ++index;int size = g[u].size();int v;instack[u] = 1;st.push(u);for(int i = 0; i < size; i++){v = g[u][i];if(!dfn[v]){tarjan(v);low[u] = min(low[u], low[v]);}else if(instack[v]) low[u] = min(low[u], dfn[v]);}if(dfn[u] == low[u]){scc++;do{v = st.top();st.pop();instack[v] = 0;fa[v] = scc;}while(v != u);}
}
void buildDag()
{for(int u = 1; u <= 2 * n; u++){int size = g[u].size();for(int i = 0; i < size; i++){int v = g[u][i];if(fa[u] != fa[v]) dag[fa[v]].push_back(fa[u]), ind[fa[u]]++;}}
}
void topsort()
{for(int i = 1; i <= scc; i++)if(ind[i] == 0) q.push(i);while(!q.empty()){int u = q.front();q.pop();if(!color[u]) color[u] = 1, color[ha[u]] = 2;int size = dag[u].size();for(int i = 0; i < size; i++){int v = dag[u][i];ind[v]--;if(ind[v] == 0) q.push(v);}}
}
void solve()
{for(int i = 1; i <= 2 * n; i++)if(!dfn[i]) tarjan(i);for(int i = 1; i <= n; i++)if(fa[i] == fa[i + n]){puts("NO");return;}else ha[fa[i]] = fa[i + n], ha[fa[i + n]] = fa[i];buildDag();topsort();printf("YES\n");for(int i = 1; i <= n; i++)if(color[fa[i]] == 1){int h1, h2, m1, m2;h1 = start[i] / 60;h2 = (start[i] + last[i]) / 60;m1 = start[i] % 60;m2 = (start[i] + last[i]) % 60;printf("%02d:%02d %02d:%02d\n", h1, m1, h2, m2);}else{int h1, h2, m1, m2;h1 = (end[i] - last[i]) / 60;h2 = end[i] / 60;m1 = (end[i] - last[i]) % 60;m2 = end[i] % 60;printf("%02d:%02d %02d:%02d\n", h1, m1, h2, m2);}
}
int main()
{int hour, miniute;while(scanf("%d", &n) != EOF){init();for(int i = 1; i <= n; i++){scanf("%d:%d", &hour, &miniute);start[i] = hour * 60 + miniute;scanf("%d:%d", &hour, &miniute);end[i] = hour * 60 + miniute;scanf("%d", &last[i]);}build();solve();}return 0;
}