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. mysql优化整理(索引)

    什么是索引? 索引是表记录的单个或多个字段重新组织的一种方法,其目的是提高数据库的查询速度,本质上就是一种数据结构. 索引的类型:primary(主键).secondary(其他) 索引的数据结构 I ...

  2. <WinForm_1>初识WinForm编程

    暑假花了一个多月自学了Win32 SDK编程,不敢说成为了高手,但是还是颇具收获——windows的消息机制(著名的消息循环).一切控件均是窗口…… 曾经有一位网友(和我一个专业的)向我吐槽:Win3 ...

  3. C# 文件上传

     一.分析 本次博客,主要解决文件上传等一系列问题,将从两方面来论述,即1G以内文件和1G以上文件. 对于上传1G以内的文件,可以采用基本的三种上传方法:用Web控件FileUpload.html控件 ...

  4. SQL 查询某字段id为空(不为空)

    1 sql 查询某字段id为空 select *  from  表名 where  id  is   null  ; 2 sql 查询某字段id不为空 select * from   表名  wher ...

  5. 获取当前位置信息-ios

    locationManager= [[CLLocationManager alloc] init];//位置管理器 locationManager.desiredAccuracy = kCLLocat ...

  6. 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&amp;颜色、光照与材质

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨)  ...

  7. 苹果的HomeKit协议

    苹果的HomeKit协议非常底层,其作用仅限于让iOS平台和家居设备能够相互“握手”,但“认识”之后,想要继续控制灯.空调等设备,仍然需要家电厂商在HomeKit的基础上进行二次开发.

  8. 大数据笔记09:大数据之Hadoop的HDFS使用

    1. HDFS使用: HDFS内部中提供了Shell接口,所以我们可以以命令行的形式操作HDFS

  9. mysql数据库的高可用方法总结

    高可用架构对于互联网服务基本是标配,无论是应用服务还是数据库服务都需要做到高可用.虽然互联网服务号称7*24小时不间断服务,但多多少少有一 些时候服务不可用,比如某些时候网页打不开,百度不能搜索或者无 ...

  10. ubuntu 安装RPM软件包

    red hat 系统用rpm格式的文件安装软件,ubuntu安装软件是用deb格式的文件安装 在ubuntu上安装rmp文件格式的软件包步骤: 1.安装转换软件 alien(需要联网) apt-get ...