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

1194: [HNOI2006]潘多拉的盒子

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 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

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 }    

 

 

posted @ 2016-04-12 13:18  TenderRun  阅读(274)  评论(0编辑  收藏  举报