洛谷 [P2661] 信息传递
来源:互联网 发布:游族网络天使纪元 编辑:程序博客网 时间:2024/05/29 08:06
求有向图的权值为一的最小环
并查集做法
维护一个dis[],表示i号元素到fa[i]的距离。
对于输入的每两个点u,v,询问这两个点的fa[]是否相同,如果相同就成环,维护最小值,mi=min(mi,dis[u]+dis[v]+1)。如果不相同,merge(u,v)。目测是最简单的做法。
但是只适用于权值为一的边。
注意对于一条U指向v的边,是将u合并到v上。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;const int MAXN=200005;int read(){ int rv=0,fh=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); } while(c>='0'&&c<='9'){ rv=(rv<<1)+(rv<<3)+c-'0'; c=getchar(); } return rv*fh;}int fa[MAXN],n,mi=0x7fffffff/3,dis[MAXN];int find(int x){ if(x!=fa[x]) { int t=fa[x];fa[x]=find(fa[x]);dis[x]+=dis[t]; } return fa[x];}void merge(int x,int y){ int r1=find(x),r2=find(y); if(r1!=r2){ fa[r1]=r2; dis[x]=dis[y]+1; }}int main(){ freopen("in.txt","r",stdin); n=read(); for(int i=1;i<=n;i++){ fa[i]=i; } for(int i=1;i<=n;i++){ int t=read(); if(find(i)==find(t)){ mi=min(mi,dis[i]+dis[t]+1); }else { merge(i,t); } } cout<<mi; fclose(stdin); return 0;}
topsort
使用拓扑排序删掉那些一定不属于环上的点,再用dfs更新最小环的数量。
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <cmath>#include <queue>using namespace std;const int MAXN=200005;int read(){ int rv=0,fh=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); } while(c>='0'&&c<='9'){ rv=(rv<<1)+(rv<<3)+c-'0'; c=getchar(); } return rv*fh;}struct edge{ int to,nxt;}e[MAXN];int n,head[MAXN],nume,in[MAXN],f[MAXN],mi=0x7fffffff/3,cnt;void adde(int from,int to){ e[++nume].to=to; e[nume].nxt=head[from]; head[from]=nume;}queue<int> q;void dfs(int u){ cnt++; f[u]=1; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(!f[v]) dfs(v); }}int main(){ freopen("in.txt","r",stdin); n=read(); for(int i=1;i<=n;i++){ int t=read(); adde(i,t); in[t]++; } for(int i=1;i<=n;i++){ if(!in[i]){ q.push(i),f[i]=1; } } while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; in[v]--; if(!in[v]&&!f[v]){ q.push(v);f[v]=1; } } } for(int i=1;i<=n;i++){ cnt=0; if(!f[i]) {dfs(i);mi=min(mi,cnt);} } cout<<mi; fclose(stdin); return 0;}
tarjan求强连通分量
最小环即强连通分量
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <cmath>#include <queue>#include <stack>using namespace std;const int MAXN=200005;int read(){ int rv=0,fh=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); } while(c>='0'&&c<='9'){ rv=(rv<<1)+(rv<<3)+c-'0'; c=getchar(); } return rv*fh;}struct edge{ int to,nxt;}e[MAXN];int n,head[MAXN],nume,dfn[MAXN],low[MAXN],in,mi=0x7fffffff/3;stack <int>s;bool f[MAXN];void adde(int from,int to){ e[++nume].to=to; e[nume].nxt=head[from]; head[from]=nume;}void tarjan(int u){ dfn[u]=++in; low[u]=++in; f[u]=1; s.push(u); for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); }else if(f[v]){ low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]){ int v=0; int cnt=0; do{ v=s.top(); s.pop(); f[v]=0; cnt++; }while(v!=u); mi=min(mi,cnt); // cout<<u<<" "<<cnt<<endl; }}int main(){ freopen("in.txt","r",stdin); n=read(); for(int i=1;i<=n;i++){ int t=read(); adde(i,t); } for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } cout<<mi; fclose(stdin); return 0;}
阅读全文
0 0
- 洛谷P2661 信息传递
- 洛谷 P2661 信息传递
- 洛谷 P2661 信息传递
- 洛谷P2661 信息传递
- 洛谷 [P2661] 信息传递
- 【NOIP2015】洛谷P2661 信息传递(tarjan)
- 水题——洛谷P2661 信息传递
- 洛谷P2661 信息传递 (NOIp2015)
- NOIp2015TG/Luogu P2661 信息传递 解题报告
- 洛谷2661 信息传递
- 【NOIP2015】洛谷2661 信息传递
- 信息传递
- NOIP2015信息传递(洛谷2661)
- 洛谷 2661 信息传递(暴力、tarjan)
- 自定义信息传递
- 窗口信息传递
- 浏览器传递参数信息
- QNX操作系统信息传递
- TensorFlow学习日记19
- phpcms入门模板配置文件修改
- django.db.utils.OperationalError: (1193, "Unknown system variable 'storage_engine'")
- 42.Oracle杂记——Oracle常用动态视图v$bh
- Python爬虫博客
- 洛谷 [P2661] 信息传递
- LuoguP1131[ZJOI2007] 时态同步 解题报告【树形DP(?)】
- mybatis-spring整合笔记
- PyCharm2017破解教程(原激活码失效)
- 抽象实例
- 微服务框架-SpringCloud简介
- 测试工具——Nunit初体验
- 10.31_两日总结
- 【git 使用详解(6)】-- 撤消操作