图论(Tarjan缩点):BZOJ 1194: [HNOI2006]潘多拉的盒子
1194: [HNOI2006]潘多拉的盒子
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 344 Solved: 181
[Submit][Status][Discuss]
Description
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
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。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 #include <stack> 6 using namespace std; 7 const int maxs=51; 8 const int maxn=51; 9 int G[maxs][maxn][2]; 10 int P[maxs][maxn],S,n,m; 11 bool vis[maxn][maxn]; 12 int cnt,fir[maxs],nxt[maxs*maxs*2],to[maxs*maxs*2]; 13 void addedge(int a,int b){ 14 nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b; 15 } 16 struct Node{ 17 int x,y; 18 }; 19 queue<Node>q; 20 void Solve(int x,int y){ 21 bool a=true,b=true; 22 memset(vis,false,sizeof(vis)); 23 q.push((Node){0,0});vis[0][0]=true; 24 while(!q.empty()){ 25 Node p=q.front();q.pop(); 26 if(P[x][p.x]^P[y][p.y]){ 27 if(P[x][p.x])b=false; 28 if(P[y][p.y])a=false; 29 } 30 if(!vis[G[x][p.x][0]][G[y][p.y][0]]){ 31 vis[G[x][p.x][0]][G[y][p.y][0]]=true; 32 q.push((Node){G[x][p.x][0],G[y][p.y][0]}); 33 } 34 if(!vis[G[x][p.x][1]][G[y][p.y][1]]){ 35 vis[G[x][p.x][1]][G[y][p.y][1]]=true; 36 q.push((Node){G[x][p.x][1],G[y][p.y][1]}); 37 } 38 } 39 if(a)addedge(y,x); 40 if(b)addedge(x,y); 41 return; 42 } 43 int ID[maxs],low[maxs],tot; 44 int cntot,ring[maxs],val[maxs],inst[maxs]; 45 stack<int>st; 46 void Tarjan(int x){ 47 ID[x]=low[x]=++tot;inst[x]=true;st.push(x); 48 for(int i=fir[x];i;i=nxt[i]){ 49 if(ID[to[i]]){ 50 if(inst[to[i]]) 51 low[x]=min(low[x],ID[to[i]]); 52 } 53 else{ 54 Tarjan(to[i]); 55 low[x]=min(low[x],low[to[i]]); 56 } 57 } 58 if(ID[x]==low[x]){ 59 while(true){ 60 int y=st.top();st.pop();inst[y]=false; 61 ring[y]=cntot;val[cntot]++; 62 if(y==x)break; 63 } 64 ++cntot; 65 } 66 } 67 int ans,ansd; 68 bool E[maxs][maxs]; 69 int path[maxs],ret[maxs]; 70 void DFS(int x,int v,int dep){ 71 bool flag=false;path[dep]=x; 72 for(int i=0;i<cntot;i++) 73 if(E[x][i]){ 74 flag=true; 75 DFS(i,v+val[i],dep+1); 76 } 77 if(!flag&&v>=ans){ 78 ans=v;ansd=dep; 79 memcpy(ret,path,sizeof(ret)); 80 } 81 return; 82 } 83 int main(){ 84 //freopen("pandora.in","r",stdin); 85 //freopen("pandora.out","w",stdout); 86 scanf("%d",&S); 87 for(int k=0;k<S;k++){ 88 scanf("%d%d",&n,&m); 89 for(int i=0,x;i<m;i++){ 90 scanf("%d",&x); 91 P[k][x]=true; 92 } 93 for(int i=0;i<n;i++) 94 scanf("%d%d",&G[k][i][0],&G[k][i][1]); 95 } 96 for(int i=0;i<S;i++) 97 for(int j=i+1;j<S;j++) 98 Solve(i,j); 99 100 for(int i=0;i<S;i++) 101 if(!ID[i]) 102 Tarjan(i); 103 104 for(int x=0;x<S;x++) 105 for(int i=fir[x];i;i=nxt[i]) 106 if(ring[to[i]]!=ring[x]) 107 E[ring[x]][ring[to[i]]]=true; 108 109 for(int i=0;i<cntot;i++) 110 DFS(i,val[i],1); 111 printf("%d\n",ans); 112 for(int i=1;i<=ansd;i++){ 113 for(int j=0;j<S;j++) 114 if(ring[j]==ret[i]){ 115 printf("%d ",j); 116 } 117 } 118 printf("\n"); 119 }
尽最大的努力,做最好的自己!