zoukankan      html  css  js  c++  java
  • 1194: [HNOI2006]潘多拉的盒子

    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

    终于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
  • 相关阅读:
    数据产品—数据仓库
    数据产品-开篇
    os.walk()
    pytest入门
    XML 文件处理
    字符编码
    消息队列
    Pycharm
    AWS入门
    Python配置模块:configparser参数含义
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3590835.html
Copyright © 2011-2022 走看看