Hdu 6162 Ch’s gift(Tarjan+dp)
来源:互联网 发布:cm是什么意思网络用语 编辑:程序博客网 时间:2024/05/29 05:57
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6162
思路:
1.强连通分量中的点必定两两可达,可将其看作一点,将图缩点。
2.对于缩点后的图,将其节点的权值设为每个连通分量的节点数。单条路径上的点对于任一点u必定存在一点v使得u可达v。则最多能u达v或v达u的点数为DAG图上权值最大的路径。判断其是否等于总点数即可。
3.dp[u]=max(dp[u],dp[v]+num[u])。
或
将图缩点后,进行拓扑排序,每个阶段若出现多于一个点其入度等于0,则此时不满足要求。任意入度为0的两个点不能相互可达。
#include<stack>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;const int maxn=1000+50;stack<int> s;int all,scc,n;int v[maxn][maxn];int vis[maxn],m;int dp[maxn];int num[maxn];int belong[maxn],d[maxn];vector<int> g[maxn],gg[maxn];int dfn[maxn],low[maxn];void Tarjan(int u){ all++; dfn[u]=low[u]=all; s.push(u),vis[u]=1; for(int i=0; i<g[u].size(); i++) { int nt=g[u][i]; if(!dfn[nt]) { Tarjan(nt); low[u]=min(low[u],low[nt]); } else if(vis[nt]) { low[u]=min(low[u],dfn[nt]); } } if(low[u]==dfn[u]) { int v; scc++; do { v=s.top(); s.pop(); belong[v]=scc; vis[v]=0; num[scc]++; } while(v!=u); }}void init(){ all=0,scc=0; memset(v,0,sizeof(v)); memset(d,0,sizeof(d)); memset(dp,0,sizeof(dp)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); while(!s.empty()) s.pop(); for(int i=0; i<=n; i++) { g[i].clear(),gg[i].clear(); } memset(belong,0,sizeof(belong));}int dfs(int u){ if(dp[u]) return dp[u]; int tmp=num[u]; for(int i=0;i<gg[u].size();i++) { int nt=gg[u][i]; tmp=max(tmp,dfs(nt)+num[u]); } return dp[u]=tmp;}int solve(){ for(int i=1; i<=n; i++) { if(dfn[i]==0) Tarjan(i); } for(int i=1; i<=n; i++) { for(int j=0; j<g[i].size(); j++) { int nt=g[i][j]; if(belong[i]==belong[nt]) continue; if(v[belong[i]][belong[nt]]) continue; gg[belong[i]].push_back(belong[nt]); d[belong[nt]]++; v[belong[i]][belong[nt]]=1; } } for(int i=1;i<=scc;i++) { if(d[i]==0) { dfs(i); break; } } int ans=0; for(int i=1;i<=scc;i++) { ans=max(dp[i],ans); } return ans==n;}int main(){#ifdef debu freopen("in.txt","r",stdin);#endif // debug int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(int i=0; i<m; i++) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); } if(!solve()) printf("Light my fire!\n"); else printf("I love you my love and our love save us!\n"); } return 0;}
阅读全文
0 0
- Hdu 6162 Ch’s gift(Tarjan+dp)
- HDU 6162 Ch’s gift(LCA)
- hdu 6162 Ch’s gift(树链刨分)
- hdu 6162 Ch’s gift
- HDU 6162 Ch’s gift
- HDU 6162 Ch’s gift
- HDU 6162 Ch's gift
- HDU 6162 Ch’s gift
- Ch’s gift HDU
- Ch’s gift HDU
- Ch’s gift HDU
- hdu 6162 Ch’s gift(主席树)
- hdu-6162 Ch’s gift 主席树
- hdu-6162 Ch’s gift(树链剖分)
- hdu 6162 Ch’s gift【树链剖分】
- hdu 6162 Ch’s gift(主席树+树链剖分)
- HDU 6162 Ch’s gift (2017多校9
- HDU 6162 Ch’s gift(树链剖分+线段树)
- 向量的计算和基本方法
- [NOIP]2016 D2T1 组合数问题
- 插入排序
- Xshell简介与安装
- ubuntu下 python分布式任务管理
- Hdu 6162 Ch’s gift(Tarjan+dp)
- 机器学习面试
- c和cpp比较(2)--读书笔记4
- 51采集PCF8591数据通过ESP8266上传C#上位机
- oracle 中的 instr 函数
- Spring
- HDU4117-GRE Words(AC自动机+DFS序+区间修改线段树)
- UVA
- sc2017新高二&高一模拟赛10 总结