NBUT 1513 Treasures【tarjan缩点+记忆化搜索】
来源:互联网 发布:ruby精粹专家编程 pdf 编辑:程序博客网 时间:2024/04/30 13:17
转载请注明出处:http://blog.csdn.net/a1dark
分析:这题真心有难度、特别是对于我这种连STL都没掌握的弱菜来说。。。只能全部用临界表存储、毕竟数据太大了、先把SCC缩点、然后一次DFS就过了。。本来想用记忆化搜索的。。但是拙计了。。先就这样做吧
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn=100005;const int maxm=150005;struct node{ int to,next;}mpt[maxm],map[maxm];int head[maxn];int low[maxn];int dfn[maxn];int vis[maxn];int que[maxn];int belong[maxn];int dp[maxn];int val[maxn];int cnt,index,top,n,m,k,w;void add(int x,int y){ mpt[k].to=y; mpt[k].next=head[x]; head[x]=k++;}int head1[maxn];void add1(int x,int y){ map[w].to=y; map[w].next=head1[x]; head1[x]=w++;}void tarjan(int s){ low[s]=dfn[s]=++index; que[++top]=s; vis[s]=1; for(int i=head[s];i!=-1;i=mpt[i].next){ int e=mpt[i].to; if(!dfn[e]){ tarjan(e); low[s]=min(low[s],low[e]); } else if(vis[e]){ low[s]=min(low[s],dfn[e]); } } if(low[s]==dfn[s]){ cnt++; int e; do{ e=que[top--]; belong[e]=cnt; val[cnt]++; vis[e]=0; }while(s!=e); }}void init(){ memset(head,-1,sizeof(head)); memset(head1,-1,sizeof(head1)); memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis)); cnt=k=w=index=0; top=-1;}int start;int maxx;void dfs(int x,int step){ if(step>maxx)maxx=step; for(int i=head1[x];i!=-1;i=map[i].next){ int s=map[i].to; dfs(s,step+val[s]); }}int main(){ int cas=1; while(scanf("%d%d%d",&n,&m,&start)!=EOF){ int a,b; init(); memset(belong,-1,sizeof(belong)); memset(val,0,sizeof(val)); for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); add(a,b); } for(int i=1;i<=n;i++){ if(!dfn[i]){ tarjan(i); } } for(int i=1;i<=n;i++){ int now=i; for(int j=head[now];j!=-1;j=mpt[j].next){ int s=mpt[j].to; if(belong[now]!=belong[s]){ add1(belong[now],belong[s]); } } } maxx=0; dfs(belong[start],val[belong[start]]); printf("Case %d:\n%d\n",cas++,maxx); } return 0;}
用记忆化搜索改进了一下:
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn=100005;const int maxm=150005;struct node{ int to,next;}mpt[maxm],map[maxm];int head[maxn];int low[maxn];int dfn[maxn];int vis[maxn];int que[maxn];int belong[maxn];int dp[maxn];int val[maxn];int cnt,index,top,n,m,k,w;void add(int x,int y){ mpt[k].to=y; mpt[k].next=head[x]; head[x]=k++;}int head1[maxn];void add1(int x,int y){ map[w].to=y; map[w].next=head1[x]; head1[x]=w++;}void tarjan(int s){ low[s]=dfn[s]=++index; que[++top]=s; vis[s]=1; for(int i=head[s];i!=-1;i=mpt[i].next){ int e=mpt[i].to; if(!dfn[e]){ tarjan(e); low[s]=min(low[s],low[e]); } else if(vis[e]){ low[s]=min(low[s],dfn[e]); } } if(low[s]==dfn[s]){ cnt++; int e; do{ e=que[top--]; belong[e]=cnt; val[cnt]++; vis[e]=0; }while(s!=e); }}void init(){ memset(head,-1,sizeof(head)); memset(head1,-1,sizeof(head1)); memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis)); cnt=k=w=index=0; top=-1;}int start;int maxx;int dfs(int x){ if(dp[x]>val[x])return dp[x]; for(int i=head1[x];i!=-1;i=map[i].next){ int s=map[i].to; dp[x]=max(dp[x],dfs(s)+val[x]); } return dp[x];}int main(){ int cas=1; while(scanf("%d%d%d",&n,&m,&start)!=EOF){ int a,b; init(); memset(belong,-1,sizeof(belong)); memset(val,0,sizeof(val)); for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); add(a,b); } for(int i=1;i<=n;i++){ if(!dfn[i]){ tarjan(i); } } for(int i=1;i<=n;i++){ int now=i; for(int j=head[now];j!=-1;j=mpt[j].next){ int s=mpt[j].to; if(belong[now]!=belong[s]){ add1(belong[now],belong[s]); } } } for(int i=1;i<=cnt;i++){ dp[i]=val[i]; } printf("Case %d:\n%d\n",cas++,dfs(belong[start])); } return 0;}
- NBUT 1513 Treasures【tarjan缩点+记忆化搜索】
- BZOJ 1589 [Usaco2008 Dec] Tarjan缩点+记忆化搜索 解题报告
- bzoj1589 [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果(tarjan缩点+记忆化搜索)
- HDU 3639 Tarjan + 缩点 + 反建图 + 搜索
- 洛谷 2921 记忆化搜索 tarjan 基环外向树
- ZOJ 3795 Grouping(强联通缩点,记忆化搜索)
- 银河之星(记忆化搜索+9点染色)
- poj1904 tarjan缩点
- HDU3836 Tarjan缩点
- HDU3836(tarjan+缩点)
- 1827 tarjan+缩点
- tarjan+缩点
- tarjan + 缩点
- Tarjan缩点
- POJ1236----tarjan缩点
- tarjan+缩点
- hdu5934 Tarjan 缩点
- poj2186--tarjan+缩点
- 接口与抽象类的区别 原文地址:http://blog.vsharing.com/jekkon/A1604115.html
- C++Vector用法
- 关于重力感应的一个小例子
- WMS-存储过程调用示例
- 五个同学的平均成绩
- NBUT 1513 Treasures【tarjan缩点+记忆化搜索】
- poj 2479 Maximum sum 两段不相交最大子段和
- [举重若轻]html5 history api实现单页面结构
- 数组大折腾
- ubuntu 创建桌面快捷方式
- windows mobile 6.5 输入法的切换
- 可变参数列表通过宏来实现(头文件stdarg.h)
- 专门针对初学者的Node.js教程
- 新人报名~~~~