1194: [HNOI2006]潘多拉的盒子 - BZOJ

Description

1194: [HNOI2006]潘多拉的盒子 - BZOJ 1194: [HNOI2006]潘多拉的盒子 - BZOJ
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

 

终于AC了

网上说的那个二元组的确很神奇,用bfs判断出两个咒语机的关系,初始状态为(0,0),状态(x,y)表示在A咒语机上x格停留,在B咒语机上y格停留

当有一个状态(x,y)x是输出元,而y不是的话,则B咒语机有一个咒语不能产生而A能产生

现在我们求出了一个有向图,要求最长链,首先就是要消去环,我们发现咒语机不可能出现A-->B-->C-->A但是A不是C的升级,相当于A>=B>=C>=A那么A,B,C相等

所以我们对点进行染色,对于一个没有染色的点,我们把和它等价的点涂成一样的颜色(也就是一个强连通分量),只要i到j有边,j到i有边,i和j就是一个强连通分量里的,否则就不是

染完色之后缩点,就是一个森林了,于是dp出最大权值链(这时点上有权,就是涂成这个颜色的点的个数)

主要是因为如果打tarjan太长了,根本不想打,而且只有50个点,明显就是给我们乱搞的嘛

 

  1 var

  2     p:array[0..50,0..50,0..1]of longint;

  3     flag,l:array[0..50,0..50]of boolean;

  4     n:longint;

  5  

  6 function max(x,y:longint):longint;

  7 begin

  8     if x>y then exit(x);

  9     exit(y);

 10 end;

 11  

 12 procedure init;

 13 var

 14     i,j,a,b,k:longint;

 15 begin

 16     read(n);

 17     for i:=1 to n do

 18       begin

 19         read(a,b);

 20         for j:=1 to b do

 21           begin

 22             read(k);

 23             flag[i,k]:=true;

 24           end;

 25         for j:=0 to a-1 do

 26           read(p[i,j,0],p[i,j,1]);

 27       end;

 28 end;

 29  

 30 var

 31     d:array[0..2500,0..1]of longint;

 32     v:array[0..50,0..50]of boolean;

 33  

 34 procedure work;

 35 var

 36     i,j,k,head,tail:longint;

 37     flagi,flagj:boolean;

 38 begin

 39     for i:=1 to n-1 do

 40       for j:=i+1 to n do

 41         begin

 42           head:=1;

 43           tail:=1;

 44           d[1,0]:=0;

 45           d[1,1]:=0;

 46           fillchar(v,sizeof(v),true);

 47           v[0,0]:=false;

 48           flagi:=true;

 49           flagj:=true;

 50           while head<=tail do

 51             begin

 52               if flag[i,d[head,0]]<>flag[j,d[head,1]] then

 53               begin

 54                 if flag[i,d[head,0]] then flagj:=false;

 55                 if flag[j,d[head,1]] then flagi:=false;

 56               end;

 57               if (flagi=false)and(flagj=false) then break;

 58               for k:=0 to 1 do

 59                 if v[p[i,d[head,0],k],p[j,d[head,1],k]] then

 60                 begin

 61                   v[p[i,d[head,0],k],p[j,d[head,1],k]]:=false;

 62                   inc(tail);

 63                   d[tail,0]:=p[i,d[head,0],k];

 64                   d[tail,1]:=p[j,d[head,1],k];

 65                 end;

 66               inc(head);

 67             end;

 68           if flagi then l[i,j]:=true;

 69           if flagj then l[j,i]:=true;

 70         end;

 71 end;

 72  

 73 var

 74     map:array[0..50,0..50]of boolean;

 75     c,f,du,s:array[0..50]of longint;

 76     vis:array[0..50]of boolean;

 77     col,num,ans:longint;

 78  

 79 procedure get;

 80 var

 81     i,j:longint;

 82 begin

 83     for i:=1 to n do

 84       if c[i]=0 then

 85       begin

 86         inc(col);

 87         c[i]:=col;

 88         inc(s[col]);

 89         for j:=1 to n do

 90           if l[i,j] and l[j,i] then

 91           begin

 92             c[j]:=col;

 93             inc(s[col]);

 94           end;

 95       end;

 96     for i:=1 to n do

 97       for j:=1 to n do

 98         if c[i]<>c[j] then

 99         if l[i,j] then map[c[i],c[j]]:=true;

100     for i:=1 to col do

101       for j:=1 to col do

102         if map[i,j] then inc(du[j]);

103     fillchar(vis,sizeof(vis),true);

104     num:=col;

105     while num>0 do

106       begin

107         for i:=1 to col do

108           if (vis[i])and(du[i]=0) then

109           begin

110             vis[i]:=false;

111             dec(num);

112             for j:=1 to col do

113               if map[i,j] then

114               begin

115                 dec(du[j]);

116                 f[j]:=max(f[j],f[i]+s[i]);

117               end;

118           end;

119       end;

120     for i:=1 to col do

121       ans:=max(ans,f[i]+s[i]);

122     write(ans);

123 end;

124  

125 begin

126     init;

127     work;

128     get;

129 end.
View Code

 

你可能感兴趣的:(ZOJ)