题目:
http://poj.org/problem?id=1904题意:
每个王子都有喜欢的妹子,给出了其中一种匹配方案,要求出每个王子能够娶的所有人,当王子娶这些妹子中的一个时其他王子都有能够娶到的喜欢的妹子。思路:
这道题的想法很精妙,因为给出了其中一个匹配方案,所以可以通过搜其他可以交换的方案,也就是在同一个强联通分量的点可以互相交换,也就可以被其中的所有王子娶。
也就从一道二分图匹配题改成了求最大连通分量的题,隐藏的很深,通常很容易当成二分图一直做下去。
另外学到了输入输出外挂,真的很有用。
代码:
#define N 112345
int flag,sum,ave,ans,res,len,ans1,ans2;
int a[N];
vector<int>g[N];
int dfn[N];
int low[N];
stack<int>st;
int inStack[N];
int belong[N];
int index,cnt;
int n,m;
void init()
{
while(!st.empty())st.pop();
memset(dfn, -1, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(inStack, 0, sizeof(inStack));
index = cnt = 1;
}
void tarjan(int x)
{
int i, a;
low[x] = dfn[x] = index;
index++;
st.push(x);
inStack[x] = 1;
int len = g[x].size();
for(i=0;i<len;i++)
{
int t=g[x][i];
if(dfn[t] == -1)
{
tarjan(t);
low[x] = min(low[x], low[t]);
}
else if(inStack[t])
low[x] = min(low[x], dfn[t]);
}
if(low[x] == dfn[x])
{
int temp;
while(!st.empty())
{
temp = st.top();
st.pop();
belong[temp] = cnt;
inStack[temp] = 0;
if(temp == x)
break;
}
cnt++;
}
}
void solve()
{
int i, j;
init();
for(i = 1; i <= n; i++)
if(dfn[i] == -1)
tarjan(i);
}
int Scan()
{
int res=0,ch,flag=0;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return flag?-res:res;
}
void Out(int a)
{
if(a>9)
Out(a/10);
putchar(a%10+'0');
}
int main()
{
int i,j,k,kk,t,x,y,z;
while(scanf("%d",&n)!=EOF&&n)
{
for(i=0;i<=2*n;i++)
g[i].clear();
for(i=1;i<=n;i++)
{
m=Scan();
for(j=0;j<m;j++)
{
t=Scan();
g[i].push_back(t+n);
}
}
for(i=1;i<=n;i++)
{
t=Scan();
g[t+n].push_back(i);
}
solve();
for(i=1;i<=n;i++)
{
x=g[i].size();m=0;
for(j=0;j<x;j++)
{
if(belong[i]==belong[g[i][j]])
a[m++]=g[i][j]-n;
}
sort(a,a+m);
Out(m);
for(j=0;j<m;j++)
{
putchar(' ');
Out(a[j]);
}
printf("\n");
}
}
return 0;
}