题目:
题解:
Y和N,两种选择,然后限制是AB不能同时不取,那么我们要添加的边就是
A′−>B
因为要输出方案,我们可以采用dfs,特别要注意,因为i+n代表N,当你看一个对称点能不能取的时候不能再用1/-1,而应该直接看ta取不取
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N=5000;
const int M=10000;
int tot,point[N],v[M],nxt[M],low[N],dfn[N],nn,stack[N],top,id,belong[N],fin[N],n,m;bool vis[N],can1,can2;
void addline(int x,int y){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}
void tarjan(int x)
{
low[x]=dfn[x]=++nn; vis[x]=1; stack[++top]=x;
for (int i=point[x];i;i=nxt[i])
if (!dfn[v[i]])
{
tarjan(v[i]); low[x]=min(low[x],low[v[i]]);
}
else if (vis[v[i]]) low[x]=min(low[x],dfn[v[i]]);
if (low[x]==dfn[x])
{
int now=0;++id;
while (now!=x)
{
now=stack[top--];
vis[now]=0;
belong[now]=id;
}
}
}
void dfs(int x,bool &can)
{
if (fin[x+n]) {can=0;return;}//
if (fin[x]) return;
stack[++top]=x;fin[x]=1;//
for (int i=point[x];i && can;i=nxt[i])
dfs(v[i],can);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)//x Y x+n N
{
char s1[5],s2[5];int x=0,y=0,z,l;
scanf("%d%s%d%s",&x,s1,&y,s2);
if (s1[0]=='Y') z=0;else z=1;
if (s2[0]=='Y') l=0;else l=1;
addline(x+(!z)*n,y+l*n);
addline(y+(!l)*n,x+z*n);
}
for (int i=1;i<=2*n;i++)
if (!dfn[i]) tarjan(i);
for (int i=1;i<=n;i++)
if (belong[i]==belong[i+n]) {printf("IMPOSSIBLE");return 0;}
for (int i=1;i<=n;i++)
{
top=0;can1=1;dfs(i,can1);
for (int j=1;j<=top;j++) fin[stack[j]]=fin[stack[j]+n]=0;
top=0;can2=1;dfs(i+n,can2);
for (int j=1;j<=top;j++) fin[stack[j]]=fin[stack[j]+n]=0;
if (can1 && !can2) printf("Y");
if (!can1 && can2) printf("N");
if (can1 && can2) printf("?");
}
}
本文介绍了一种利用Tarjan算法解决二分图匹配问题的方法,通过构造特殊的图结构并运用深度优先搜索(DFS)来寻找可能的匹配方案。文章详细展示了如何通过添加边来确保满足题目条件,并通过Tarjan算法找到强连通分量,从而判断是否存在可行解。
543

被折叠的 条评论
为什么被折叠?



