POJ2723

来源:互联网 发布:java两个时间相减 编辑:程序博客网 时间:2024/05/29 16:03

Problem : Get Luffy Out
Description :

2N把钥匙,分成了N份,每份两把钥匙,使用了其中一把,另一把就会自动消失,现在有M层楼,每层楼有扇门,每扇门有两把锁,打开其中任意一把都可以打开这个门。现在问你用这些钥匙最多能开几扇门,注意,只有打开了前一层楼的门才能有机会开下一层楼的门?

Solution :

二分答案+2SAT问题。把一份钥匙看成一个布尔型变量。因为题目中说了只能按顺序开门,那么就可以二分开门的数量,我开始看错题了,以为开门的顺序可以任意,那么这样就不好二分了。然后就是按照门上的锁建边,这里建边的依据就是两把钥匙不能同时都不用!最后2-SAT判定就好了。

Code(C++) :

#include <stdio.h>#include <string.h>#define MIN(a,b) ((a)>(b)? (b):(a))const int M=(1<<13);typedef struct tagEdge{    int to,next;    tagEdge(){}    tagEdge(int to,int next):to(to),next(next){}}Edge;int n,m;int dfn[M],low[M];int belong[M];bool used[M];int after_deal_n;int sum;Edge e[M*M+500];int head[M];int num_e;int que[M*M];int top;int a[M],b[M];int hash_index[M];void addedge(int from,int to){    e[num_e]=Edge(to,head[from]);    head[from]=num_e++;}void tarjan(int x){    dfn[x]=low[x]=++sum;    que[top++]=x;    used[x]=true;    for(int i=head[x];i+1;i=e[i].next){        int to=e[i].to;        if(!dfn[to]){            tarjan(to);            low[x]=MIN(low[x],low[to]);        }else if(used[to])            low[x]=MIN(low[x],dfn[to]);    }    if(dfn[x]==low[x]){        ++after_deal_n;        int node;        do{            node=que[--top];            used[node]=false;            belong[node]=after_deal_n;        }while(node!=x);    }}void init(){    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(belong,-1,sizeof(belong));    memset(used,false,sizeof(used));    after_deal_n=0;    top=0;    num_e=0;    sum=0;}bool judge(int num){    init();    for(int i=0;i<num;i++){        addedge(a[i],hash_index[b[i]]);        addedge(b[i],hash_index[a[i]]);        //addedge(hash_index[a[i]],b[i]);        //addedge(hash_index[b[i]],a[i]);    }    for(int i=0;i<2*n;i++)        if(!dfn[i])            tarjan(i);    for(int i=0;i<2*n;i++)        if(belong[i]==belong[hash_index[i]])            return false;    return true;}int main(){    //freopen("in.data","r",stdin);    while(scanf("%d%d",&n,&m),n+m){        int x,y;        for(int i=0;i<n;i++){            scanf("%d%d",&x,&y);            hash_index[x]=y;            hash_index[y]=x;        }        for(int i=0;i<m;i++)            scanf("%d%d",&a[i],&b[i]);        int ans=0;        int l=0,r=m,mid;        while(l<=r){            mid=(l+r)/2;            if(judge(mid)){                ans=mid;                l=mid+1;            }else                r=mid-1;        }        printf("%d\n",ans);    }    return 0;}
0 0