题目大意:
有n对钥匙和m扇门,每个门上有两把锁,打开其中任何一把锁该扇门都会打开。
钥匙总是成对出现,一旦选择一对中的一个钥匙后,该对的另一个钥匙就会消失。并且只有通过前一扇门才可以去往下一扇门。问当前你已经拥有所有钥匙并知道所有门上锁的情况下,最多能到达多少扇门。
解题思路:
首先确定钥匙必须2选1,即对应了2-SAT的模型。那么接下来就是约束条件了,约束条件毫无疑问是用门上的锁来进行的。
假如门上的锁是a b,我们暂且认为 与 a b 对应的是 a‘ b’ ,那么就意味着我们必须选择这两把中的一个钥匙来打开这扇门,这里正着想不是很好想,我们可以理解为如果我们选择了a‘ 这里必须选b 选择了b’就必须选a,然后以此建边,
剩下的就是二分最远能到达的距离,不停的check只能找出最终答案即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int INF=1e9+7;
int n,m,idx[maxn];
vector<int> v[maxn],r[maxn];
struct node
{
int x,y;
}door[maxn];
int tot,cnt,low[maxn],dfn[maxn],belong[maxn];
bool vis[maxn];
stack<int> s;
void tarjan(int u)
{
low[u]=dfn[u]=++tot;
s.push(u),vis[u]=1;
for(int i=0;i<v[u].size();i++)
{
int now=v[u][i];
if(!dfn[now])
{
tarjan(now);
low[u]=min(low[u],low[now]);
}
else if(vis[now])
low[u]=min(low[u],dfn[now]);
}
if(dfn[u]==low[u])
{
cnt++;
while(!s.empty())
{
int now=s.top();
vis[now]=0,s.pop();
belong[now]=cnt;
if(now==u) break;
}
}
}
void add(int x,int y) { v[x].push_back(y); }
int opp[maxn],sl[maxn],color[maxn];
void init()
{
tot=0,cnt=0;
for(int i=0;i<=2*n;i++) v[i].clear(),r[i].clear();
for(int i=0;i<=2*n;i++) low[i]=dfn[i]=belong[i]=0;
for(int i=0;i<=2*n;i++) sl[i]=0,vis[i]=0;
}
bool judge()
{
for(int i=1;i<=n;i++)
if(belong[i]==belong[i+n]) return 0;
return 1;
}
bool check(int num)
{
init();
for(int i=1;i<=num;i++)
{
add(idx[opp[door[i].x]],idx[door[i].y]); //添加约束条件
add(idx[opp[door[i].y]],idx[door[i].x]);
}
for(int i=1;i<=2*n;i++)
if(!dfn[i]) tarjan(i);
if(judge()) return 1; //判断是否合法
return 0;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<=2*n;i++) opp[i]=0;
if(n==0&&m==0) break;
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
x++,y++;
opp[x]=y,opp[y]=x; //把每对钥匙标记为成对
idx[x]=i,idx[y]=i+n;
}
for(int i=1;i<=m;i++) scanf("%d%d",&door[i].x,&door[i].y),door[i].x++,door[i].y++;
int L=0,R=m,ans=0;
while(L<=R) //二分最远距离
{
int mid=(L+R)>>1;
if(check(mid)) ans=mid,L=mid+1;
else R=mid-1;
}
printf("%d\n",ans);
//system("pause");
}
}
扫描二维码关注公众号,回复:
2322766 查看本文章