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;
}
View Code

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;
}
View Code

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
", ans);
    return 0;
}
View Code

据说这题用并查集代码还会短,心态不爆炸的时候再来补吧。

原文地址:https://www.cnblogs.com/phemiku/p/11834912.html