【codevs2131】【BZOJ1924】所驼门王的宝藏,tarjan+拓扑DP
2016-06-01 17:41
447 查看
Time:2016.06.01
Author:xiaoyimi
转载注明出处谢谢
传送门1
传送门2
思路:
比较简单
使用规则建出一个包含N个点的无向图来,然后tarjan,得到重构后的有向无环图,然后拓扑DP就可以了
f[u]代表以i为起点所能走到的最多的点数
f[u]=max(f[v])∀(u,v)∈E
由DP方程我们可以开出来要求出点i的f值,必须要求它所有能到达的点的f值,所以我们可以反向建图拓扑排序,这样就能求出全部的f值了
注意:
1.建原图时处理起来很烦人,我用vector存储同一行、列的点,map存储周围一圈的点,所以常数大得吓人……
2.存边的数组一定要开大点……
代码:
Author:xiaoyimi
转载注明出处谢谢
传送门1
传送门2
思路:
比较简单
使用规则建出一个包含N个点的无向图来,然后tarjan,得到重构后的有向无环图,然后拓扑DP就可以了
f[u]代表以i为起点所能走到的最多的点数
f[u]=max(f[v])∀(u,v)∈E
由DP方程我们可以开出来要求出点i的f值,必须要求它所有能到达的点的f值,所以我们可以反向建图拓扑排序,这样就能求出全部的f值了
注意:
1.建原图时处理起来很烦人,我用vector存储同一行、列的点,map存储周围一圈的点,所以常数大得吓人……
2.存边的数组一定要开大点……
代码:
#include<bits/stdc++.h> #include<map> #define M 100004 #define LL long long using namespace std; int in() { int t=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) t=(t<<3)+(t<<1)+ch-48,ch=getchar(); return t; } int k=in(),n=in(),m=in(),tot,cnt; int IN[M],OUT[M],f[M],belong[M],siz[M],low[M],dfn[M],X[M],Y[M],T[M],first[M]; int dx[8]={0,0,-1,-1,-1,1,1,1},dy[8]={-1,1,-1,0,1,-1,0,1}; vector<int>a[M*10],b[M*10]; bool vis[M]; stack<int>S; queue<int>Q; map<LL,int>mp; struct edge{int v,next;}e[M*40]; void add(int x,int y){e[++tot]=(edge){y,first[x]};first[x]=tot;} void dfs(int x) { low[x]=dfn[x]=++cnt; S.push(x); vis[x]=1; for (int i=first[x];i;i=e[i].next) if (!dfn[e[i].v]) dfs(e[i].v), low[x]=min(low[e[i].v],low[x]); else if (vis[e[i].v]) low[x]=min(dfn[e[i].v],low[x]); if(low[x]==dfn[x]) for (int y=-1;y!=x;y=S.top(),S.pop()) siz[x]++, vis[S.top()]=0, belong[S.top()]=x; } main() { for (int i=1;i<=k;i++) X[i]=in(),Y[i]=in(),T[i]=in(), mp[(LL)(X[i]-1)*m+Y[i]]=i, a[X[i]].push_back(i), b[Y[i]].push_back(i); for (int i=1;i<=k;i++) { if(T[i]==1) for (int j=0;j<a[X[i]].size();j++) if (i!=a[X[i]][j]) add(i,a[X[i]][j]); else; else if (T[i]==2) for (int j=0;j<b[Y[i]].size();j++) if (i!=b[Y[i]][j]) add(i,b[Y[i]][j]); else; else for (int j=0;j<8;j++) { LL t=(LL)(X[i]+dx[j]-1)*m+Y[i]+dy[j]; int x=mp[t]; if(x) add(i,x); } } for (int i=1;i<=k;i++) if(!dfn[i]) dfs(i); tot=0; memset(first,0,sizeof(first)); for (int i=1;i<=k;i++) { if(T[i]==1) for (int j=0;j<a[X[i]].size();j++) if (belong[i]!=belong[a[X[i]][j]]) IN[belong[i]]++, OUT[a[X[i]][j]]++, add(belong[a[X[i]][j]],belong[i]); else; else if (T[i]==2) for (int j=0;j<b[Y[i]].size();j++) if (belong[i]!=belong[b[Y[i]][j]]) IN[belong[i]]++, OUT[b[Y[i]][j]]++, add(belong[b[Y[i]][j]],belong[i]); else; else for (int j=0;j<8;j++) { LL t=(LL)(X[i]+dx[j]-1)*m+Y[i]+dy[j]; int x=mp[t]; if(x&&belong[i]!=belong[x]) IN[belong[i]]++, OUT[belong[x]]++, add(belong[x],belong[i]); } } for (int i=1;i<=k;i++) if (!IN[i]&&siz[i]) Q.push(i), f[i]=siz[i]; for (;!Q.empty();Q.pop()) { int x=Q.front();vis[x]=0; for (int i=first[x];i;i=e[i].next) { if (f[e[i].v]<f[x]+siz[e[i].v]) f[e[i].v]=f[x]+siz[e[i].v]; IN[e[i].v]--; if (!IN[e[i].v]) Q.push(e[i].v); } } for (int i=1;i<=k;i++) f[0]=max(f[0],f[i]); printf("%d",f[0]); }
相关文章推荐
- 第14周项目2-两个成员的类模板2
- Struts2登录拦截器的简单示例
- Android开发笔记之:Handler Runnable与Thread的区别详解
- adb安装apk
- 模拟添加联系人
- oracle触发器
- perl JSON与HASH 互相转换
- python中列表,元组的乘法
- 非技术经验
- hd 2050 折线分割平面
- 单链表(增、删、查找)
- c语言实现的的map
- 猴子吃桃问题
- 求球的反弹高度
- 编写一个函数,它从一个字符串中提取一个子字符串。
- 用函数实现乘法口诀表,其中口诀表的行数和列数是自己指定
- 《Python基础教程》学习笔记 Chp7 更加抽象
- 字符串替换空格:请实现一个函数,把字符串中的每个空格替换成“%20。
- 求闰年的!!!
- (T.T) 打印100到200之间的素数