您的位置:首页 > 其它

【2-SAT】POJ 3207

2012-01-27 00:11 302 查看
这题读起来有点蛋疼,真是英语害死人!

题意是有n个点在圆的边缘,编号是0~n-1顺时针,有m条线(不一定是直线,线可以再圆内,也可以再圆外),问是否存在所有线不想交的情况

方法:2-SAT,以所有线为点,两两枚举,假设i代表在圆内,i'代表圆外,如果线i与线j在圆内相交,就连i---j'还有j---i',注意要连双向边,然后就套模板,如果两个矛盾点在同一个强连通分量里就false。

#define N 1111
vector<int> v
;
stack<int> s;
bool vis
;
bool inStack
;
int low
,dfn
;
int belong
;//属于哪个强连通分量
int n,m,step,t;
struct node{
int s,t;
}p
;
void init(){
int i;
for(i=0;i<=2*n;i++){
v[i].clear();
vis[i] = 0;
inStack[i] = 0;
}
while(!s.empty())s.pop();
}
void add(int a,int b){
v[a].push_back(b);
}
//tarjan缩点
void tarjan(int u){
vis[u]=true;
step++;
s.push(u);
inStack[u]=true;
low[u]=step,dfn[u]=step;
int i,j;
for(i=0;i<v[u].size();i++)
{
int x=v[u][i];
if(!vis[x])
{
tarjan(x);
low[u]=min(low[u],low[x]);
}
else
if(inStack[x])
low[u]=min(low[u],dfn[x]);
}
if(low[u]==dfn[u])
{
t++;
while(1)
{
int x=s.top();
s.pop();
belong[x]=t;
inStack[x]=false;
if(x==u)break;
}
}
}

void solve(){
t = 0,step = 0;
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if((p[i].s < p[j].s && p[i].t < p[j].t && p[i].t > p[j].s) || (p[i].s > p[j].s && p[i].t > p[j].t && p[i].s < p[j].t)){
add(i,j+n);
add(j+n,i);
add(j,i+n);
add(i+n,j);
}
}
}
for(i=0;i<2*n;i++){
if(!vis[i])tarjan(i);
}
for(i=0;i<n;i++){
if(belong[i] == belong[i+n]){
puts("the evil panda is lying again");
return ;
}
}
puts("panda is telling the truth...");
}
int main(){
while(scanf("%d%d",&m,&n) != -1){
int i;
init();
for(i=0;i<n;i++){
scanf("%d%d",&p[i].s,&p[i].t);
if(p[i].s > p[i].t)swap(p[i].s,p[i].t);
}
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: