P2661 [NOIP2015 提高组] 信息传递 提交 92.72k 通过 32.68k 时间限制 1.00s 内存限制 125.00MB
>>>
题意很清楚,求图中最小的环。
如果一个人的入度为0,则肯定不可能成环,那么把这个人和他连出的边删去(即标记这个人并将他下一个人的入度减 1),
如果下一个人的入度为0则将他也删去……最后把所有入度为0的人都删去了,剩下的都是环。
每个人的出度为1,所以每个人只能在一个环中,每条边只能在一个环中,也就是说每个环都是分开的,
然后进行一遍 dfs,找出最小的环。
>>>关系看成一个有向图。对于任意一个节点进入,因为每个点的出度均为1,所以最多只能构成三种情况:1、一条链;2、一个环链;3、一条链连接着一个环链。
>>>在每次加入时查看是否有环 若无则连接 否则 维护答案 环从任一点进入都可以
:::find(x) 基操 cmp 按部就班
:::有环时不要 连接 or 死循环
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <algorithm> #include <queue> using namespace std; int n,t[200050],d[200050],ans=1000000000,r[200050]; void read(int& x){ x=0; int y=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') y=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } x=x*y; } void dfs(int ti,int s,int l){ if (ti==s&&l){ //如果回到开始说明连成了环 ans=min(ans,l); return; } if (!d[t[ti]]) { d[t[ti]]=1; //标记 dfs(t[ti],s,l+1); } } void rmove(int ti){ //删除ti d[ti]=-1; //标记 r[t[ti]]--; //ti的下一个人的入度减一 if (!r[t[ti]]&&d[t[ti]]!=-1) rmove(t[ti]); } int main(){ //freopen("ferry.in","r",stdin); //freopen("message.out","w",stdout); memset(d,0,sizeof(d)); memset(r,0,sizeof(r)); //r[i]为第 i 个人的入度 int i; read(n); for (i=1;i<=n;i++){ read(t[i]); r[t[i]]++; } for (i=1;i<=n;i++){ if (!r[i]&&d[i]!=-1) rmove(i); //如果 i 的入度为 0 且还未被删除,则删除i } for (i=1;i<=n;i++){ if (!d[i]){ //如果i还未搜过且未被删除,则从i开始搜索 //cout<<i<<' '; dfs(i,i,0); } } //cout<<endl; printf("%d",ans); return 0; } /*#include <iostream> #include <cstdio> using namespace std; const int N = 200010; int n, fa[N], ans = 0x3f3f3f3f; int get (int x, int &cnt) { //cnt记录环的长度 cnt ++; if (fa[x] == x) return x; else return get(fa[x], cnt); } // cmp with return fa[x]==x? x: fa[x]=find(fa[x]) //->缩短查询 更改 fa 信息 int main () { //因为 rd==1 -> fa -> 唯一->从不同出发 scanf("%d", &n); for (int i = 1; i <= n; i ++) fa[i] = i; for (int i = 1; i <= n; i ++) { int cnt = 0, f; scanf("%d", &f); if (get(f, cnt) == i) { ans = min(ans, cnt); //维护最小的环 }else fa[i] = f; } printf("%d", ans); return 0; }*/

浙公网安备 33010602011771号