NOIP2015信息传递(拓扑排序 / 并查集)
【题意】求最小环长
【解题】我恨这个题
我是一个没有读题的杀手傻手
20分代码(单环)
//第二题 #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> #define fr(i,n) for( int i = 1; i <= n; ++i) const int N = 2e5 + 9; int idv[N],x,sum,n,son[N]; std::queue<int>q; int main(){ scanf("%d",&n); fr(i,n){ scanf("%d",&x); idv[x]++; son[i] = x; } fr(i,n) if(!idv[i]) { sum++; q.push(i); break;} while(!q.empty()){ int x = q.front(); q.pop(); if(!idv[x]){ ////////////////// int v = son[x]; idv[v]--; if(idv[v] == 0){ sum++; q.push(v); } else break; /////////////////////// } } printf("%d",n - sum); return 0; }
60分代码
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> #define min(x,y) ((x)<(y)?(x):(y)) #define fr(i,n) for(register int i = 1; i <= n; ++i) const int N = 2e5 + 9; int idv[N],x,sum,ans = 0x3f3f3f,n,son[N],vis[N],temp; std::queue<int>q; int main(){ scanf("%d",&n); fr(i,n){ scanf("%d",&x); idv[x]++; son[i] = x; } fr(i,n) if(!idv[i]){ idv[son[i]]--;} fr(i,n){ if (!vis[i] && idv[i] != 0){ vis[i] = 1; temp = 1; int v = son[i]; while (!vis[v]){ vis[v] = 1; v = son[v]; temp++; } ans = min(ans,temp); } } printf("%d",ans); return 0; }
100分
#include <cstdio> #include <cstring> #include <queue> #include <iostream> #include <algorithm> #define min(x,y) ((x)<(y)?(x):(y)) using namespace std; const int N = 200050; int to[N],vis[N], idv[N]; int n,ans,temp,j; queue <int> q; int main(){ scanf("%d", &n); ans = n; for (int i = 1; i <= n; i++){ scanf("%d", &to[i]); ++idv[to[i]]; } for (int i = 1; i <= n; i++) if (idv[i] == 0){ q.push(i); vis[i] = 1; } while (!q.empty()){ int u = q.front(); q.pop(); --idv[to[u]]; if (idv[to[u]] == 0) { vis[to[u]] = 1; q.push(to[u]); } } for (int i = 1; i <= n; i++){ if (!vis[i] && idv[i] != 0){ vis[i] = 1; temp = 1; j = to[i]; while (!vis[j]){ vis[j] = 1; j = to[j]; temp++; } ans = min(ans,temp); } } printf("%d\n", ans); return 0; }
据说这题用并查集代码还会短,心态不爆炸的时候再来补吧。
满堂花醉三千客,一剑霜寒十四州