图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子

时间:2022-06-16 04:08:01

1194: [HNOI2006]潘多拉的盒子

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 344  Solved: 181
[Submit][Status][Discuss]

Description

图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子

图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子

Input

第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50)。文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述。每一块的格式如下。 一块的第一行有两个正整数n,m。分别表示该咒语机中元件的个数、咒语源输出元的个数(1≤m≤n≤50)。 接下来一行有m个数,表示m个咒语源输出元的标号(都在0到n-1之间)。接下来有n行,每一行两个数。第i行(0≤i≤n-1)的两个数表示pi,0和pi,1(当然,都在0到n-1之间)。

Output

第一行有一个正整数t,表示最长升级序列的长度。

Sample Input

4
1 1
0
0 0
2 1
0
1 1
0 0
3 1
0
1 1
2 2
0 0
4 1
0
1 1
2 2
3 3
0 0

Sample Output

3

  原题要输出方案,可是这里没有SPJ。

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
using namespace std;
const int maxs=;
const int maxn=;
int G[maxs][maxn][];
int P[maxs][maxn],S,n,m;
bool vis[maxn][maxn];
int cnt,fir[maxs],nxt[maxs*maxs*],to[maxs*maxs*];
void addedge(int a,int b){
nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;
}
struct Node{
int x,y;
};
queue<Node>q;
void Solve(int x,int y){
bool a=true,b=true;
memset(vis,false,sizeof(vis));
q.push((Node){,});vis[][]=true;
while(!q.empty()){
Node p=q.front();q.pop();
if(P[x][p.x]^P[y][p.y]){
if(P[x][p.x])b=false;
if(P[y][p.y])a=false;
}
if(!vis[G[x][p.x][]][G[y][p.y][]]){
vis[G[x][p.x][]][G[y][p.y][]]=true;
q.push((Node){G[x][p.x][],G[y][p.y][]});
}
if(!vis[G[x][p.x][]][G[y][p.y][]]){
vis[G[x][p.x][]][G[y][p.y][]]=true;
q.push((Node){G[x][p.x][],G[y][p.y][]});
}
}
if(a)addedge(y,x);
if(b)addedge(x,y);
return;
}
int ID[maxs],low[maxs],tot;
int cntot,ring[maxs],val[maxs],inst[maxs];
stack<int>st;
void Tarjan(int x){
ID[x]=low[x]=++tot;inst[x]=true;st.push(x);
for(int i=fir[x];i;i=nxt[i]){
if(ID[to[i]]){
if(inst[to[i]])
low[x]=min(low[x],ID[to[i]]);
}
else{
Tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
}
if(ID[x]==low[x]){
while(true){
int y=st.top();st.pop();inst[y]=false;
ring[y]=cntot;val[cntot]++;
if(y==x)break;
}
++cntot;
}
}
int ans,ansd;
bool E[maxs][maxs];
int path[maxs],ret[maxs];
void DFS(int x,int v,int dep){
bool flag=false;path[dep]=x;
for(int i=;i<cntot;i++)
if(E[x][i]){
flag=true;
DFS(i,v+val[i],dep+);
}
if(!flag&&v>=ans){
ans=v;ansd=dep;
memcpy(ret,path,sizeof(ret));
}
return;
}
int main(){
//freopen("pandora.in","r",stdin);
//freopen("pandora.out","w",stdout);
scanf("%d",&S);
for(int k=;k<S;k++){
scanf("%d%d",&n,&m);
for(int i=,x;i<m;i++){
scanf("%d",&x);
P[k][x]=true;
}
for(int i=;i<n;i++)
scanf("%d%d",&G[k][i][],&G[k][i][]);
}
for(int i=;i<S;i++)
for(int j=i+;j<S;j++)
Solve(i,j); for(int i=;i<S;i++)
if(!ID[i])
Tarjan(i); for(int x=;x<S;x++)
for(int i=fir[x];i;i=nxt[i])
if(ring[to[i]]!=ring[x])
E[ring[x]][ring[to[i]]]=true; for(int i=;i<cntot;i++)
DFS(i,val[i],);
printf("%d\n",ans);
for(int i=;i<=ansd;i++){
for(int j=;j<S;j++)
if(ring[j]==ret[i]){
printf("%d ",j);
}
}
printf("\n");
}