http://poj.org/problem?id=3683
1,根据矛盾建边
2,tarjan求scc判断可行性
3,根据scc缩点建反向边
4,拓扑排序,按顺序输出选择情况
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
#include<cstdlib>
using namespace std;
const int maxn = 2005;
int n;
int st[maxn], ed[maxn];
vector<int> e[maxn], reverseE[maxn];
stack<int> s;
bool instack[maxn];
int dfn[maxn], low[maxn], scc[maxn], sccn, step;
int in[maxn], op[maxn];
int mark[maxn];
bool check(int x, int y){
if (st[x] >= ed[y] || ed[x] <= st[y]) return false;
return true;
}
void init(){
scanf("%d", &n);
int a, b, c, d, t;
for (int i = 0; i < n; i++){
scanf("%d:%d %d:%d %d", &a, &b, &c, &d, &t);
int t1 = a*60+b, t2 = c*60+d;
st[i*2] = t1; ed[i*2] = t1+t;
st[i*2+1] = t2-t; ed[i*2+1] = t2;
}
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (i != j){
if (check(2*i, 2*j)) e[2*i].push_back(2*j+1);
if (check(2*i, 2*j+1)) e[2*i].push_back(2*j);
if (check(2*i+1, 2*j)) e[2*i+1].push_back(2*j+1);
if (check(2*i+1, 2*j+1)) e[2*i+1].push_back(2*j);
}
}
}
}
void tarjan(int x){
dfn[x] = low[x] = ++step;
s.push(x); instack[x] = true;
int sz = e[x].size();
for (int i = 0; i < sz; i++){
int to = e[x][i];
if (!dfn[to]){
tarjan(to);
low[x] = min(low[x], low[to]);
}
else if (instack[to])
low[x] = min(low[x], dfn[to]);
}
if (dfn[x] == low[x]){
sccn++;
int now = 0;
do{
now = s.top();
s.pop();
instack[now] = false;
scc[now] = sccn;
}while(now != x);
}
}
void solve(){
sccn = step = 0;
memset(instack, false, sizeof(instack));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(scc, 0, sizeof(scc));
memset(in, 0, sizeof(in));
for (int i = 0; i < 2*n; i++)
if (!dfn[i]) tarjan(i);
for (int i = 0; i < n; i++){
if (scc[2*i] == scc[2*i+1]){
printf("NO\n");
return ;
}
op[scc[2*i]] = scc[2*i+1]; op[scc[2*i+1]] = scc[2*i];
}
printf("YES\n");
for (int i = 0; i < 2*n; i++){
int sz = e[i].size();
for (int j = 0; j < sz; j++){
int to = e[i][j];
if (scc[i] != scc[to])
reverseE[scc[to]].push_back(scc[i]), in[scc[i]]++;
}
}
queue<int> q;
for (int i = 1; i <= sccn; i++)
if (in[i] == 0) q.push(i);
memset(mark, 0, sizeof(mark));
while(!q.empty()){
int from = q.front();
q.pop();
if (mark[from] == 0){
mark[from] = 1;
mark[op[from]] = -1;
}
int sz = reverseE[from].size();
for (int i = 0; i < sz; i++){
if (--in[reverseE[from][i]] == 0) q.push(reverseE[from][i]);
}
}
int a, b, c, d;
for (int i = 0; i < n; i++){
if (mark[scc[2*i]] == 1){
a = st[2*i]/60;
b = st[2*i]%60;
c = ed[2*i]/60;
d = ed[2*i]%60;
}
else{
a = st[2*i+1]/60;
b = st[2*i+1]%60;
c = ed[2*i+1]/60;
d = ed[2*i+1]%60;
}
printf("%02d:%02d %02d:%02d\n", a, b, c, d);
}
}
int main(){
init();
solve();
return 0;
}