<tarjan||拓扑>codevs 2066 三角恋
来源:互联网 发布:淘宝卖什么比较冷门 编辑:程序博客网 时间:2024/05/17 07:22
去题面的传送门
第一次做超时了,只得了四十分。
做法是dfs找大小为3的环。数据范围是2000,一定超时。
下面是40分的代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=2000+10;int cnt,t,n;int nxt[maxn*maxn],fist[maxn];bool flg,bo;bool vis[maxn][maxn],used[maxn];struct hh{ int f,t;}e[maxn*maxn];void build(int f,int t){ e[++cnt]=(hh){f,t}; nxt[cnt]=fist[f]; fist[f]=cnt;}void init(){ cnt=flg=0; memset(fist,-1,sizeof(fist)); memset(nxt,0,sizeof(nxt)); memset(e,0,sizeof(e)); memset(vis,0,sizeof(vis)); memset(used,0,sizeof(used));}bool dfs(int x,int k){ for(int i=fist[x];i!=-1;i=nxt[i]) { int v=e[i].t; if(k>3&&vis[v][k+1-3]) { bo=1; return true; } vis[v][k+1]=true; used[v]=true; dfs(v,k+1); if(bo) return true; vis[v][k+1]=false; } vis[x][k]=false; if(!bo) return false; else return true;}int main(){ scanf("%d",&t); while(t--) { init(); scanf("%d",&n); for(int i=1;i<=n;++i) { string s; cin>>s; for(int j=0;j<n;++j) if(s[j]=='1') build(i,j+1); } for(int i=1;i<=n;++i) if(!used[i]) { used[i]=true; vis[i][1]=true; bo=0; if(dfs(i,1)) { flg=1; break; } } if(flg) printf("Yes\n"); else printf("No\n"); } return 0;}
我又尝试先把不可能构成环的节点删除,也就是拓扑找入度为0的点,然后再进行dfs。但是这样仍然超时,代码是这样:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int maxn=2000+10;int cnt,t,n;int nxt[maxn*maxn],fist[maxn],ru[maxn];bool flg,bo;bool used[maxn];struct hh{ int f,t;}e[maxn*maxn];queue<int>q;void build(int f,int t){ e[++cnt]=(hh){f,t}; nxt[cnt]=fist[f]; fist[f]=cnt;}void init(){ cnt=flg=0; memset(ru,0,sizeof(ru)); memset(fist,-1,sizeof(fist)); memset(nxt,0,sizeof(nxt)); memset(e,0,sizeof(e)); memset(used,0,sizeof(used)); while(!q.empty()) q.pop();}bool dfs(int x,int k,int num){ for(int i=fist[x];i!=-1;i=nxt[i]) { int v=e[i].t; if(k==3&&v==num) { bo=1; return true; } if(used[v]) continue; if(k<4) dfs(v,k+1,num); if(bo) return true; } if(bo) return true; else return false;}void topu(){ for(int i=1;i<=n;++i) if(!ru[i]) { q.push(i); used[i]=true; } while(!q.empty()) { int u=q.front(); q.pop(); for(int i=fist[u];i!=-1;i=nxt[i]) { int v=e[i].t; if(ru[v]) ru[v]--; else { used[v]=true; q.push(v); } } }}int main(){ scanf("%d",&t); while(t--) { init(); scanf("%d",&n); for(int i=1;i<=n;++i) { char s[maxn]; scanf("%s",s); for(int j=0;j<n;++j) if(s[j]=='1') { ru[j+1]++; build(i,j+1); } } topu(); for(int i=1;i<=n;++i) if(!used[i]) { used[i]=true; bo=0; if(dfs(i,1,i)) { flg=1; break; } } if(flg) printf("Yes\n"); else printf("No\n"); } return 0;}
这时候我就懵了
百度题解是找环,能找到环就是存在三角恋(wtf??)
应该是理解错题面了,不一定非得是三个人??
那就上拓扑找环的代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int maxn=2000+10;int t,n,cnt,ans;int fist[maxn],nxt[maxn*maxn],ru[maxn];struct hh{ int f,t;}e[maxn*maxn];queue<int>q;void build(int f,int t){ e[++cnt]=(hh){f,t}; nxt[cnt]=fist[f]; fist[f]=cnt;}void init(){ cnt=ans=0; memset(e,0,sizeof(e)); memset(ru,0,sizeof(ru)); memset(fist,-1,sizeof(fist)); memset(nxt,0,sizeof(nxt)); while(!q.empty()) q.pop();}void topu(){ for(int i=1;i<=n;++i) if(!ru[i]) { ans++; q.push(i); } while(!q.empty()) { int u=q.front(); q.pop(); for(int i=fist[u];i!=-1;i=nxt[i]) { int v=e[i].t; if(ru[v]) ru[v]--; if(!ru[v]) { ans++; q.push(v); } } }}int main(){ scanf("%d",&t); while(t--) { scanf("%d",&n); init(); for(int i=1;i<=n;++i) { string s; cin>>s; for(int j=0;j<n;++j) if(s[j]=='1') { ru[j+1]++; build(i,j+1); } } topu(); if(ans==n) printf("No\n"); else printf("Yes\n"); } return 0;}
然后是tarjan做法
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>using namespace std;const int maxn=2000+10;int n,t,cnt,scc_cnt,Index;int fist[maxn],nxt[maxn*maxn],dfn[maxn],low[maxn],scc[maxn];bool flg;struct hh{ int f,t;}e[maxn*maxn];stack<int>s;void init(){ cnt=flg=0; memset(fist,-1,sizeof(fist)); memset(nxt,0,sizeof(nxt)); memset(e,0,sizeof(e)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(scc,0,sizeof(scc)); while(!s.empty()) s.pop();}void build(int f,int t){ e[++cnt]=(hh){f,t}; nxt[cnt]=fist[f]; fist[f]=cnt;}void tarjan(int i){ if(flg) return; dfn[i]=low[i]=++Index; s.push(i); for(int j=fist[i];j!=-1;j=nxt[j]) { int v=e[j].t; if(!dfn[v]) { tarjan(v); low[i]=min(low[i],low[v]); } else if(!scc[v]) low[i]=min(low[i],dfn[v]); } if(low[i]==dfn[i]) { scc_cnt++; int j,tot=0; do { j=s.top(); s.pop(); tot++; scc[j]=scc_cnt; } while(i!=j); if(tot>1) { flg=1; return ; } }}int main(){ scanf("%d",&t); while(t--) { scanf("%d",&n); init(); for(int i=1;i<=n;++i) { string s; cin>>s; for(int j=0;j<n;++j) if(s[j]=='1') build(i,j+1); } for(int i=1;i<=n;++i) if(!scc[i]) tarjan(i); if(flg) printf("Yes\n"); else printf("No\n"); } return 0;}
阅读全文
0 0
- <tarjan||拓扑>codevs 2066 三角恋
- Codevs 2066 三角恋
- codevs 2066 三角恋
- codevs 2066 三角恋(dfs)
- 【codevs】1506 传话 Tarjan
- codevs-2822 (Tarjan)
- codevs 2822(tarjan)
- BZOJ1924 tarjan+拓扑序
- codevs 1332 上白泽慧音(Tarjan)
- codevs 2604 舞会邀请 tarjan
- codevs 舞会邀请(Tarjan)
- 最优贸易-tarjan+拓扑更新
- bzoj 3887 tarjan+拓扑排序
- [codevs 2822] 爱在心中 【tarjan 算法】
- codevs 2822 爱在心中(Tarjan)
- <tarjan算法模板> codevs 1332 上白泽慧音
- codevs 1506 传话 Tarjan 解题报告
- codevs 2604 舞会邀请(tarjan)
- Spring Boot——开发新一代Spring Java应用
- ABB副总裁顾纯元:柔性自动化怎么帮助制造业的转型升级?
- 详情:微软 262 亿美元收购 LinkedIn,后者将保持独立
- 【金融量化】我以为我是食物链顶层的收割者,想不到只是别人手中的镰刀
- linux系统中cut的用法
- <tarjan||拓扑>codevs 2066 三角恋
- Python 模拟知乎登陆,保存登陆cookie
- dubbo安装
- Idea快捷键设置复制上一行
- 一行行看SDWebImage源码(最新版本v4.1.2)
- 【java-日志组件】slf4j+logback配置及详解
- C3P0和DBCP数据库连接池的
- 苹果WWDC官方推荐,腾讯手机管家终结iPhone诈骗电话
- JavaScript知识夯实系列-4.运算符