http://www.lydsy.com/JudgeOnline/problem.php?id=1194

我们看看怎么判断B是否是A的升级。

我们新建一个图G,每个点为一个二元组(i,j),表示A的i号点和B的j号点。

设A中i号点的0出边为p0[i],B中j号点的0出边为p0[j],那么在图G中(i,j)连一条有向边到(p0[i],p0[j])

同理,设A中i号点的1出边为p1[i],B中j号点的1出边为p1[j],那么在图G中(i,j)连一条有向边到(p1[i],p1[j])

我们在图G中从(0,0)点开始BFS,如果到了某个点(i,j),在A中i号是输出点,但是在B中j号点不是输出点,那么B不是A的升级。

如果没出现上面那种情况,那么B是A的升级。

现在已知道了各个咒语机的升级关系了。

如果B是A的升级,那么连有向边A->B。

我们要在这个有向图中找一条最长路径。

先缩点,变成有向无环图,然后拓扑排序。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b) for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=; int S;
struct Tdata
{
int N,M,flag[maxN+],p[maxN+][];
inline void input()
{
int i;
N=gint();M=gint();
mmst(flag,);
re(i,,M)flag[gint()+]=;
re(i,,N)p[i][]=gint()+,p[i][]=gint()+;
}
}data[maxN+]; int vis[maxN+][maxN+];
int head,tail;
PII que[maxN*maxN+];
inline int check(int a,int b)
{
mmst(vis,);
que[head=tail=]=PII(,);
vis[][]=;
if(data[a].flag[] && !data[b].flag[])return ;
while(head<=tail)
{
int i,x=que[head].fi,y=que[head].se;head++;
re(i,,)
{
int tx=data[a].p[x][i],ty=data[b].p[y][i];
if(vis[tx][ty])continue;
vis[tx][ty]=;
que[++tail]=PII(tx,ty);
if(data[a].flag[tx] && !data[b].flag[ty])return ;
}
}
return ;
} int now,first[maxN+];
struct Tedge{int v,next;}edge[maxN*maxN+];
inline void addedge(int u,int v){now++;edge[now].v=v;edge[now].next=first[u];first[u]=now;}
int tot,idx[maxN+],val[maxN+],f[maxN+],form[maxN+],ans;
vector<int> G[maxN+]; int cnt,low[maxN+],dfn[maxN+],vis2[maxN+];
int top,sta[maxN+];
inline void Tarjan(int u)
{
dfn[u]=low[u]=++cnt;
vis2[sta[++top]=u]=;
int i,v;
for(i=first[u],v=edge[i].v;i!=-;i=edge[i].next,v=edge[i].v)
if(!vis2[v])
{
Tarjan(v);
upmin(low[u],low[v]);
}
else
if(vis2[v]==) upmin(low[u],dfn[v]);
if(low[u]==dfn[u])
{
++tot;
while()
{
idx[sta[top]]=tot;
val[tot]++;
G[tot].push_back(sta[top]);
vis2[sta[top]]=;
top--;
if(sta[top+]==u)break;
}
}
} int du[maxN+];
int ge,h[maxN+];
Tedge t[maxN*maxN+];
inline void addedge2(int u,int v){ge++;t[ge].v=v;t[ge].next=h[u];h[u]=ge;} int Q[maxN+]; int ds,out[maxN+]; int main()
{
/*freopen("bzoj1194.in","r",stdin);
freopen("bzoj1194.out","w",stdout);*/
int i,j;
S=gint();
re(i,,S)data[i].input();
mmst(first,-);now=-;
re(i,,S)re(j,,S)if(i!=j && check(i,j))addedge(i,j);/*,PF("%d->%d\n",i,j);*/
re(i,,S)if(!vis2[i])Tarjan(i);
ge=-;mmst(h,-);
int u,v;
re(u,,S)for(i=first[u],v=edge[i].v;i!=-;i=edge[i].next,v=edge[i].v)if(idx[u]!=idx[v])addedge2(idx[u],idx[v]),du[idx[v]]++;
head=;tail=-;
re(i,,tot)if(du[i]==)Q[++tail]=i,f[i]=val[i],form[i]=;
while(head<=tail)
{
int u=Q[head++],v;
for(i=h[u],v=t[i].v;i!=-;i=t[i].next,v=t[i].v)
{
if(val[v]+f[u]>f[v])f[v]=val[v]+f[u],form[v]=u;
du[v]--;
if(du[v]==)Q[++tail]=v;
}
}
int p;
ans=;
re(i,,tot)if(f[i]>ans)ans=f[i],p=i;
cout<<ans<<endl;
/*while(p)out[++ds]=p,p=form[p];
red(i,ds,1)re(j,0,int(G[out[i]].size())-1)PF("%d ",G[out[i]][j]-1);PF("\n");*/
return ;
}

bzoj 1194的更多相关文章

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

    1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 344  Solved: 181[Submit][Stat ...

  2. BZOJ 1194: [HNOI2006]潘多拉的盒子( BFS + tarjan + dp )

    O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路.. ------------------------------------- ...

  3. BZOJ 1194 [HNOI2006]潘多拉的盒子 (图论+拓扑排序+tarjan)

    题面:洛谷传送门 BZOJ传送门 标签里三个算法全都是提高组的,然而..这是一道神题 我们把这道题分为两个部分解决 1.找出所有咒语机两两之间的包含关系 2.求出咒语机的最长上升序列 我们假设咒语机$ ...

  4. BZOJ 1194: [HNOI2006]潘多拉的盒子 [DP DFA]

    传送门 题意: s个DFA,选出尽量多的自动机a0, a1, a2, . . . , at,使得a1包含a0.a2包 含a1,以此类推.s ≤ 50. DFA的字符集为{0,1},有的节点是输出源,节 ...

  5. 潘多拉的盒子(bzoj 1194)

    Description Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述.每一块的格 ...

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

    Description  Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述.每一块的 ...

  7. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  8. BZOJ 2693: jzptab [莫比乌斯反演 线性筛]

    2693: jzptab Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1194  Solved: 455[Submit][Status][Discu ...

  9. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

随机推荐

  1. PE基金的运作模式有哪些?

    一.信托制(1)信托型基金是由基金管理机构与信托公司合作设立,通过发起设立信托受益份额募集资金,然后进行投资运作的集合投资工具(2)信托公司和基金管理机构组成决策委员会实施,共同进行决策(3)在内部分 ...

  2. 限定checkbox最多选中数量

    一.概述: checkbox是我们在编写网页的时候经常使用的多选框,但是有些时候我们会限定最多选中的数量,如何限定呢? 下面这例子限定了最多选中两个元素,并且将这两个选中的源依次显示在一个文本框里: ...

  3. parcel write boolean值

    http://stackoverflow.com/questions/6201311/how-to-read-write-a-boolean-when-implementing-the-parcela ...

  4. windows 7 SDK和DDK下载地址

    查个小资料,得到地址,顺便记录一下. Windows Driver Kit Version 7.1.0 http://www.microsoft.com/downloads/details.aspx? ...

  5. PHP页面之间跳转方法总结

    编程中,在页面之间进行跳转是必须的.这里列出了三种办法,供参考. 一.用HTTP头信息 也就是用PHP的HEADER函数.PHP里的HEADER函数的作用就是向浏览器发出由HTTP协议规定的本来应该通 ...

  6. java开发webservice的几种方式

    webservice的应用已经越来越广泛了,下面介绍几种在Java体系中开发webservice的方式,相当于做个记录. 1.Axis2 Axis是apache下一个开源的webservice开发组件 ...

  7. Ngnix安装

    一.pcre安装 yum install pcre 或 https://sourceforge.net/projects/pcre/files/pcre/8.37/ 手动下载后上传至linux 1.y ...

  8. RxJava漫谈-RxAndroid使用

    RxJava在github上的地址:https://github.com/ReactiveX/RxJava RxAndroid在github上的地址:https://github.com/Reacti ...

  9. jQuery Scroll div滚动条样式更改

    <script type="text/javascript" src="js/jquery-1.2.6.min.js"></script> ...

  10. AD DIV 层的知识 和 行为特效

    1.AP(绝对定位) 2.使用AP DIV层和表格结合起来完美布局网页 3.层的Z轴值越大,该层就位于比较顶的位置 4.层有可见性的属性,层溢出,层的裁剪, 5层嵌套,先把光标定位在外层里面,然后拖多 ...