BZOJ 1924 && Luogu P2403 [SDOI2010]所驼门王的宝藏 恶心建图+缩点DP
记住:map一定要这么用:
if(mp[x[i]+dx[j]].find(y[i]+dy[j])!=mp[x[i]+dx[j]].end()) add(i,mp[x[i]+dx[j]][y[i]+dy[j]]);
而不是
R tmp=mp[x[i]+dx[j]][y[i]+dy[j]]; if(tmp) add(i,tmp);
别问我为什么QAQ
建图:选定一个横天门,向在这一行上的横天门连无向边,剩下的门连有向边;纵寰门一样的方法
用map判 自由_门 旁边八个点是否存在,存在就连边;
最后tarjan缩点,用dp求最长路
#include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<map> #define R register int const int dx[]={0,1,1,1,0,-1,-1,-1},dy[]={1,1,0,-1,-1,-1,0,1}; using namespace std; inline int g() { R ret=0; register char ch; while(!isdigit(ch=getchar())) ; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret; } #define pb(x) push_back(x) int k,n,m,cnt=1,ind,cc,top,ans,num; int lst[100010],lst2[100010],x[100010],y[100010],op[100010],d[100010]; int vr[1000010],nxt[1000010],fir[1000010],dfn[100010],scc[100010],stk[100010],low[100010],c[100010]; vector<int>a[1000010],b[1000010]; map<int,int> mp[1000010]; bool vis[100010]; inline void add(int u,int v) {if(u==v) return ;vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} inline void init() { for(R i=1;i<=n;++i) { R x=0,sz=a[i].size(); for(R j=0;j<sz;++j) if(op[a[i][j]]==1) {x=a[i][j]; break;} for(R j=0;j<sz;++j) {add(x,a[i][j]); if(op[a[i][j]]==1) add(a[i][j],x);} } for(R i=1;i<=m;++i) { R x=0,sz=b[i].size(); for(R j=0;j<sz;++j) if(op[b[i][j]]==2) {x=b[i][j]; break;} for(R j=0;j<sz;++j) {add(x,b[i][j]); if(op[b[i][j]]==2) add(b[i][j],x);} } for(R i=1;i<=k;++i) if(op[i]==3) for(R j=0;j<8;++j) if(mp[x[i]+dx[j]].find(y[i]+dy[j])!=mp[x[i]+dx[j]].end()) add(i,mp[x[i]+dx[j]][y[i]+dy[j]]);void tarjan(int u) { low[u]=dfn[u]=++num; stk[++top]=u,vis[u]=true; for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { R tmp; ++cc; do tmp=stk[top],--top,vis[tmp]=false,c[tmp]=cc,++scc[cc]; while(tmp!=u); } } int vv[1000010],nn[1000010],ff[1000010]; inline void addc(int u,int v) {vv[++cnt]=v,nn[cnt]=ff[u],ff[u]=cnt;} inline void solve() { cnt=1; for(R u=1;u<=k;++u) for(R i=fir[u];i;i=nxt[i]) if(c[u]!=c[vr[i]]) addc(c[u],c[vr[i]]); } inline void dp(int u) { vis[u]=true; for(R i=ff[u];i;i=nn[i]) { R v=vv[i]; if(!vis[v]) dp(v); d[u]=max(d[v],d[u]); } d[u]+=scc[u]; ans=max(d[u],ans); } signed main() { k=g(),n=g(),m=g(); for(R i=1;i<=k;++i) { x[i]=g(),y[i]=g(),op[i]=g(); mp[x[i]][y[i]]=i; a[x[i]].pb(i),b[y[i]].pb(i); } init(); for(R i=1;i<=k;++i) if(!dfn[i]) tarjan(i); solve(); memset(vis,false,sizeof(vis)); for(R i=1;i<=cc;++i) if(!vis[i]) dp(i); printf("%d\n",ans); return 0; }
2019.04.21