表面看这道题是二分匹配,但是想深入一点,发现它是求强连通。为啥这样说呢?因为开始时先把单向边由男的连向女的,根据最后一行又由女的连向男的,然后就用tarjan缩点求强连通,注意把男的编号是1~n,女的编号是n+1~2n,还要注意最后输出是升序的,所以要sort一下(没注意到wa了一次)。
下面附上sample的二分图:

男左女右。。。红色为双向边,tarjan后就变成一个点,黑色的是单向边。。。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <limits.h>
using namespace std;
int lowbit(int t){return t&(-t);}
int countbit(int t){return (t==0)?0:(1+countbit(t&(t-1)));}
int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a>b?b:a;}
#define LL long long
#define PI acos(-1.0)
#define N 4010
#define INF INT_MAX
#define eps 1e-8
#define FRE freopen("a.txt","r",stdin)
vector<int> v[N];
int low[N],dfn[N],belong[N];
bool inStack[N];
bool vis[N];
int step;
int t;
stack<int> st;
int n;
void tarjan(int u)
{
step++;
low[u]=dfn[u]=step;
inStack[u]=1;
vis[u]=1;
st.push(u);
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=st.top();
st.pop();
belong[x]=t;
inStack[x]=0;
if(x==u)break;
}
}
}
void work()
{
int i,j;
int ans[N];
memset(vis,0,sizeof(vis));
for(i=1;i<=2*n;i++)
if(!vis[i])tarjan(i);
for(i=1;i<=n;i++)
{
int x=belong[i];
int cnt=0;
for(j=0;j<v[i].size();j++)
{
if(belong[v[i][j]]==x)
ans[cnt++]=v[i][j]-n;
}
sort(ans,ans+cnt);
printf("%d",cnt);
for(j=0;j<cnt;j++)
printf(" %d",ans[j]);
printf("\n");
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int i,j,k;
for(i=0;i<=2*n;i++)v[i].clear();
while(!st.empty())st.pop();
for(i=1;i<=n;i++)
{
int m;
scanf("%d",&m);
while(m--)
{
int a;
scanf("%d",&a);
v[i].push_back(a+n);
}
}
for(i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
v[a+n].push_back(i);
}
step=0;
t=0;
work();
}
return 0;
}
本文介绍了一个利用Tarjan算法求解强连通分量的问题,并通过实例展示了如何构建二分图并进行Tarjan缩点求解。文章详细解释了Tarjan算法的应用过程及注意事项。
1116

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



