bzoj 1194
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-9; inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); inline int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } inline LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxN=50; int S; struct Tdata { int N,M,flag[maxN+10],p[maxN+10][2]; inline void input() { int i; N=gint();M=gint(); mmst(flag,0); re(i,1,M)flag[gint()+1]=1; re(i,1,N)p[i][0]=gint()+1,p[i][1]=gint()+1; } }data[maxN+10]; int vis[maxN+10][maxN+10]; int head,tail; PII que[maxN*maxN+100]; inline int check(int a,int b) { mmst(vis,0); que[head=tail=0]=PII(1,1); vis[1][1]=1; if(data[a].flag[1] && !data[b].flag[1])return 0; while(head<=tail) { int i,x=que[head].fi,y=que[head].se;head++; re(i,0,1) { int tx=data[a].p[x][i],ty=data[b].p[y][i]; if(vis[tx][ty])continue; vis[tx][ty]=1; que[++tail]=PII(tx,ty); if(data[a].flag[tx] && !data[b].flag[ty])return 0; } } return 1; } int now,first[maxN+10]; struct Tedge{int v,next;}edge[maxN*maxN+100]; inline void addedge(int u,int v){now++;edge[now].v=v;edge[now].next=first[u];first[u]=now;} int tot,idx[maxN+10],val[maxN+10],f[maxN+10],form[maxN+10],ans; vector<int> G[maxN+10]; int cnt,low[maxN+10],dfn[maxN+10],vis2[maxN+10]; int top,sta[maxN+10]; inline void Tarjan(int u) { dfn[u]=low[u]=++cnt; vis2[sta[++top]=u]=1; int i,v; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v) if(!vis2[v]) { Tarjan(v); upmin(low[u],low[v]); } else if(vis2[v]==1) upmin(low[u],dfn[v]); if(low[u]==dfn[u]) { ++tot; while(1) { idx[sta[top]]=tot; val[tot]++; G[tot].push_back(sta[top]); vis2[sta[top]]=2; top--; if(sta[top+1]==u)break; } } } int du[maxN+10]; int ge,h[maxN+10]; Tedge t[maxN*maxN+100]; inline void addedge2(int u,int v){ge++;t[ge].v=v;t[ge].next=h[u];h[u]=ge;} int Q[maxN+10]; int ds,out[maxN+10]; int main() { /*freopen("bzoj1194.in","r",stdin); freopen("bzoj1194.out","w",stdout);*/ int i,j; S=gint(); re(i,1,S)data[i].input(); mmst(first,-1);now=-1; re(i,1,S)re(j,1,S)if(i!=j && check(i,j))addedge(i,j);/*,PF("%d->%d\n",i,j);*/ re(i,1,S)if(!vis2[i])Tarjan(i); ge=-1;mmst(h,-1); int u,v; re(u,1,S)for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(idx[u]!=idx[v])addedge2(idx[u],idx[v]),du[idx[v]]++; head=0;tail=-1; re(i,1,tot)if(du[i]==0)Q[++tail]=i,f[i]=val[i],form[i]=0; while(head<=tail) { int u=Q[head++],v; for(i=h[u],v=t[i].v;i!=-1;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]==0)Q[++tail]=v; } } int p; ans=0; re(i,1,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 0; }