POJ 2723 二分+2-SAT
Get Luffy Out
| Time Limit: 2000MS | Memory Limit: 65536K | |
| Total Submissions: 6910 | Accepted: 2638 |
Description
Ratish is a young man who always dreams of being a
hero. One day his friend Luffy was caught by Pirate Arlong. Ratish set off at
once to Arlong's island. When he got there, he found the secret place where his
friend was kept, but he could not go straight in. He saw a large door in front
of him and two locks in the door. Beside the large door, he found a strange
rock, on which there were some odd words. The sentences were encrypted. But that
was easy for Ratish, an amateur cryptographer. After decrypting all the
sentences, Ratish knew the following facts:
Behind the large door, there
is a nesting prison, which consists of M floors. Each floor except the deepest
one has a door leading to the next floor, and there are two locks in each of
these doors. Ratish can pass through a door if he opens either of the two locks
in it. There are 2N different types of locks in all. The same type of locks may
appear in different doors, and a door may have two locks of the same type. There
is only one key that can unlock one type of lock, so there are 2N keys for all
the 2N types of locks. These 2N keys were divided into N pairs, and once one key
in a pair is used, the other key will disappear and never show up again.
Later, Ratish found N pairs of keys under the rock and a piece of paper
recording exactly what kinds of locks are in the M doors. But Ratish doesn't
know which floor Luffy is held, so he has to open as many doors as possible. Can
you help him to choose N keys to open the maximum number of doors?
hero. One day his friend Luffy was caught by Pirate Arlong. Ratish set off at
once to Arlong's island. When he got there, he found the secret place where his
friend was kept, but he could not go straight in. He saw a large door in front
of him and two locks in the door. Beside the large door, he found a strange
rock, on which there were some odd words. The sentences were encrypted. But that
was easy for Ratish, an amateur cryptographer. After decrypting all the
sentences, Ratish knew the following facts:
Behind the large door, there
is a nesting prison, which consists of M floors. Each floor except the deepest
one has a door leading to the next floor, and there are two locks in each of
these doors. Ratish can pass through a door if he opens either of the two locks
in it. There are 2N different types of locks in all. The same type of locks may
appear in different doors, and a door may have two locks of the same type. There
is only one key that can unlock one type of lock, so there are 2N keys for all
the 2N types of locks. These 2N keys were divided into N pairs, and once one key
in a pair is used, the other key will disappear and never show up again.
Later, Ratish found N pairs of keys under the rock and a piece of paper
recording exactly what kinds of locks are in the M doors. But Ratish doesn't
know which floor Luffy is held, so he has to open as many doors as possible. Can
you help him to choose N keys to open the maximum number of doors?
Input
There are several test cases. Every test case starts
with a line containing two positive integers N (1 <= N <= 210)
and M (1 <= M <= 211) separated by a space, the first integer
represents the number of types of keys and the second integer represents the
number of doors. The 2N keys are numbered 0, 1, 2, ..., 2N - 1. Each of the
following N lines contains two different integers, which are the numbers of two
keys in a pair. After that, each of the following M lines contains two integers,
which are the numbers of two keys corresponding to the two locks in a door. You
should note that the doors are given in the same order that Ratish will meet. A
test case with N = M = 0 ends the input, and should not be processed.
with a line containing two positive integers N (1 <= N <= 210)
and M (1 <= M <= 211) separated by a space, the first integer
represents the number of types of keys and the second integer represents the
number of doors. The 2N keys are numbered 0, 1, 2, ..., 2N - 1. Each of the
following N lines contains two different integers, which are the numbers of two
keys in a pair. After that, each of the following M lines contains two integers,
which are the numbers of two keys corresponding to the two locks in a door. You
should note that the doors are given in the same order that Ratish will meet. A
test case with N = M = 0 ends the input, and should not be processed.
Output
For each test case, output one line containing an
integer, which is the maximum number of doors Ratish can open.
integer, which is the maximum number of doors Ratish can open.
Sample Input
3 6 0 3 1 2 4 5 0 1 0 2 4 1 4 2 3 5 2 2 0 0
Sample Output
4
题意:
有一些个门, 还有2 * n个钥匙分成了n组,每组里有两把钥匙,并且每组中只能使用一把钥匙,
然后每个门有两把锁,分别对应着钥匙,两个锁只要任意开一个门就会打开,并且,要打开一个门,必须保证他序号之前的所有门都打开了,类似于一关一关的往里闯然后思路的话,由于是必须顺序的开门,所以可以进行二分枚举答案,如果枚举的数为m, 则我们要判定的就是1~m的门是否能被打开,
就要用2-sat建图判定了。
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
using namespace std;
const int maxn=90000;
const int maxm=9000000;
int head[maxn],low[maxn],dfn[maxn],tol,Stack[maxn],instack[maxn],belong[maxn],indexx,scc,top,n,id[maxn];
struct node
{
int to,next;
}edge[maxm];
void add(int u,int v)
{
edge[tol].next=head[u];
edge[tol].to=v;
head[u]=tol++;
}
struct Node
{
int x,y;
}pp[maxn];
void tarjin(int u)
{
low[u]=dfn[u]=++indexx;
Stack[top++]=u;instack[u]=1;
int i,v;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjin(v);
if(low[u]>low[v])low[u]=low[v];
}
else if(instack[v]&&low[u]>dfn[v])low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
scc++;
do
{
v=Stack[--top];
instack[v]=0;
belong[v]=scc;
}while(u!=v);
}
}
int solve(int mid)
{
memset(head,-1,sizeof(head));tol=0;
int i,j;
for(i=1;i<=mid;i++)
{
add(pp[i].x,pp[i].y^1);
add(pp[i].y,pp[i].x^1);
}
memset(instack,0,sizeof(instack));
memset(dfn,0,sizeof(dfn));
scc=indexx=top=0;
memset(belong,0,sizeof(belong));
for(i=0;i<4*n;i++)if(!dfn[i])tarjin(i);
for(i=0;i<2*n;i++)if(belong[2*i]==belong[2*i+1])return 0;
return 1;
}
int main()
{
int i,j,k,m,T;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
int cnt=0;
for(k=0;k<n;k++)
{
scanf("%d%d",&i,&j);
id[i]=cnt++;
id[j]=cnt++;
}
for(i=1;i<=m;i++)
{
scanf("%d%d",&j,&k);
pp[i].x=id[j];
pp[i].y=id[k];
}
// for(i=0;i<2*n;i++)cout<<id[i]<<endl;
// for(i=1;i<=m;i++)cout<<pp[i].x<<" "<<pp[i].y<<endl;
int left=1,right=m,mid;
while(left<right)
{
mid=(left+right+1)>>1;
if(solve(mid))left=mid;
else right=mid-1;
}
printf("%d\n",left);
// cout<<solve(5)<<endl;
}
return 0;
}
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
using namespace std;
const int maxn=90000;
const int maxm=9000000;
int head[maxn],low[maxn],dfn[maxn],tol,Stack[maxn],instack[maxn],belong[maxn],indexx,scc,top,n,id[maxn];
struct node
{
int to,next;
}edge[maxm];
void add(int u,int v)
{
edge[tol].next=head[u];
edge[tol].to=v;
head[u]=tol++;
}
struct Node
{
int x,y;
}pp[maxn];
void tarjin(int u)
{
low[u]=dfn[u]=++indexx;
Stack[top++]=u;instack[u]=1;
int i,v;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjin(v);
if(low[u]>low[v])low[u]=low[v];
}
else if(instack[v]&&low[u]>dfn[v])low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
scc++;
do
{
v=Stack[--top];
instack[v]=0;
belong[v]=scc;
}while(u!=v);
}
}
int solve(int mid)
{
memset(head,-1,sizeof(head));tol=0;
int i,j;
for(i=1;i<=mid;i++)
{
add(pp[i].x,pp[i].y^1);
add(pp[i].y,pp[i].x^1);
}
memset(instack,0,sizeof(instack));
memset(dfn,0,sizeof(dfn));
scc=indexx=top=0;
memset(belong,0,sizeof(belong));
for(i=0;i<4*n;i++)if(!dfn[i])tarjin(i);
for(i=0;i<2*n;i++)if(belong[2*i]==belong[2*i+1])return 0;
return 1;
}
int main()
{
int i,j,k,m,T;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
int cnt=0;
for(k=0;k<n;k++)
{
scanf("%d%d",&i,&j);
id[i]=cnt++;
id[j]=cnt++;
}
for(i=1;i<=m;i++)
{
scanf("%d%d",&j,&k);
pp[i].x=id[j];
pp[i].y=id[k];
}
// for(i=0;i<2*n;i++)cout<<id[i]<<endl;
// for(i=1;i<=m;i++)cout<<pp[i].x<<" "<<pp[i].y<<endl;
int left=1,right=m,mid;
while(left<right)
{
mid=(left+right+1)>>1;
if(solve(mid))left=mid;
else right=mid-1;
}
printf("%d\n",left);
// cout<<solve(5)<<endl;
}
return 0;
}

浙公网安备 33010602011771号