upc-WNJXYK and DIDIDI and monkey(并查集启发式合并)

题目描述

DIDIDI and WNJXYK are good friends. One day, they go to the zoo. The monkeys are playing happily. There are n monkeys named 1-n. At first, the first one hangs its tail on the tree. The other n-1 monkeys, either are caught by other monkeys, or catch other monkeys, or both. In the next m seconds, every second, there will be a monkey releasing its left hand or right hand. And then some monkeys will drop on the floor. Given the relationship between monkeys, calculate the landing time of every monkey.

输入

The first line of input contains a positive integer T, telling you there are T test cases followed.
Each test case, first line includes two integers n, m. n means number of monkeys, and m as mentioned in the description.
Then following n lines, the k-th line has two integers, describe the k-th monkey’s information. The first integer is the index of monkey in its left hand, the second integer is the index of monkey in its right hand. -1 indicates there is nothing in its hand.
Then following m lines, the i-th line gives the information at time i-1, every line has two numbers, the first is the index of the monkey, the second is the hand that it releases, 1 is left hand, 2 is right hand.
It’s guaranteed that all the monkeys aren’t on the floor at the beginning.

输出

For each test case, print a line “Case #x: ”, where x is the case number (starting from 1) and print n integers. The i-th integer is the time monkey i drop in the floor. If monkey i don’t land on the floor, print -1;

样例输入
1
3 2
-1 3
3 -1
1 2
1 2
3 1
样例输出
Case #1: -1 1 1
提示

Tips:1≤T≤10,1≤n≤200,000,0≤m≤400,000
Initially, the first monkey’s tail hangs on the tree. The first monkey’s right hand catches the third monkey, the second monkey’s left hand catches the third monkey, and the third’s left hand catches the first monkey while the right hand catches the second. On time 0, the first monkey releases its right hand, no monkey lands on the floor. On time 1, the third monkey releases its left hand, then the second monkey and the third land on the floor.

题意

n 只猴子( 标号 1 - n ),m 个时刻 , 一开始给出 n 只猴子左右手牵的是哪只猴子( - 1 就是没牵),然后接下来 m 行给出每个时刻哪只猴子放开哪只手,最后让你给出 m 个时刻后,每只猴子在哪个时刻掉下去( - 1 代表没掉下去)(一开始只有 1 号猴子 尾巴 挂在树上)

思路

看猴子是不是掉下去就是判断和 1 是不是联通,可以倒着考虑这个题,把松手倒过来,看做从最后一次开始抓,用并查集启发式合并集合的那些元素,然后看看和 1 是不是连通,如果联通,就把答案时刻存下来。(还是看代码吧(((φ(◎ロ◎;)φ))))

代码
#include<iostream>
#include<string>
#include<map>
#include<set>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define best 131 
#define INF 0x3f3f3f3f
#define P pair<int,int>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps=1e-7;
const double pai=acos(-1.0);
const int N=2e4+10;
const int maxn=4e5+10;
const int mod=1e9+7;
//const int d[4][2]={0,1,1,0,-1,0,0,-1};
int pre[maxn],ans[maxn];
vector<int>deep[maxn];
pair<int,int>p[maxn];
int vis[maxn][3],to[maxn][3];
int find(int x)
{
    if(pre[x]==x) return x;
    else return pre[x]=find(pre[x]);
} 
void unions1(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx==fy) return;
    if(deep[fx].size()>deep[fy].size()) swap(fx,fy);
    pre[fx]=fy;
    deep[fy].insert(deep[fy].end(),deep[fx].begin(),deep[fx].end());
}
void unions2(int x,int y,int t)
{
    if(y==-1) return;
    int fx=find(x);
    int fy=find(y);
    if(fx==fy) return;
    int f1=find(1);
    if(fx==f1)
    {
        for(int i=0;i<deep[fy].size();i++)
            ans[deep[fy][i]]=t;
    }
    if(fy==f1)
    {
        for(int i=0;i<deep[fx].size();i++)
            ans[deep[fx][i]]=t;
    }
    if(deep[fx].size()>deep[fy].size()) swap(fx,fy);
    pre[fx]=fy;
    deep[fy].insert(deep[fy].end(),deep[fx].begin(),deep[fx].end());
}
void init(int n)
{
    for(int i=1;i<=n;i++) 
    {
        deep[i].clear();
        pre[i]=i;ans[i]=-1;
        deep[i].push_back(i);
        vis[i][1]=0;vis[i][2]=0;
    }
}
int main()
{
//  ios::sync_with_stdio(false);
    //memset(mp,-1,sizeof(mp));
    int t,n,m,x,y,tot=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init(n);
        for(int i=1;i<=n;i++) 
        {
            scanf("%d%d",&x,&y);
            to[i][1]=x;to[i][2]=y;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&p[i].first,&p[i].second);
            vis[p[i].first][p[i].second]=1;
        } 
        for(int i=1;i<=n;i++) 
        {
            for(int j=1;j<=2;j++)
            {
                if(to[i][j]==-1||vis[i][j]) continue;
                unions1(i,to[i][j]);
            } 
        }
        for(int i=m;i>=1;i--) 
        {
            unions2(p[i].first,to[p[i].first][p[i].second],i-1);
        }
        printf("Case #%d: ",++tot);
        for(int i=1;i<n;i++) printf("%d ",ans[i]);
        printf("%d\n",ans[n]);
    }
    return 0;
}
LeNet-5神经网络 C源代码,这个写的比较好,可以用gcc编译去跑,结合理论可以对深度学习有更深刻的了解 介绍 根据YANN LECUN的论文《Gradient-based Learning Applied To Document Recognition》设计的LeNet-5神经网络,C语言写成,不依赖任何第三方库。 MNIST手写字符集初代训练识别率97%,多代训练识别率98%。 DEMO main.c文件为MNIST数据集的识别DEMO,直接编译即可运行,训练集60000张,测试集10000张。 项目环境 该项目为VISUAL STUDIO 2015项目,用VISUAL STUDIO 2015 UPDATE1及以上直接打开即可编译。采用ANSI C编写,因此源码无须修改即可在其它平台上编译。 如果因缺少openmp无法编译,请将lenet.c中的#include和#pragma omp parallel for删除掉即可。 API #####批量训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 inputs: 要训练的多个图片对应unsigned char二维数组的数组,指向的二维数组的batchSize倍大小内存空间指针。在MNIST测试DEMO中二维数组为28x28,每个二维数组数值分别为对应位置图像像素灰度值 resMat:结果向量矩阵 labels:要训练的多个图片分别对应的标签数组。大小为batchSize batchSize:批量训练输入图像(二维数组)的数量 void TrainBatch(LeNet5 *lenet, image *inputs, const char(*resMat)[OUTPUT],uint8 *labels, int batchSize); #####单个训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 要训练的图片对应二维数组 resMat:结果向量矩阵 label: 要训练的图片对应的标签 void Train(LeNet5 *lenet, image input, const char(*resMat)[OUTPUT],uint8 label); #####预测 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 输入的图像的数据 labels: 结果向量矩阵指针 count: 结果向量个数 return 返回值为预测的结果 int Predict(LeNet5 *lenet, image input, const char(*labels)[LAYER6], int count); #####初始化 lenet: LeNet5的权值的指针,LeNet5神经网络的核心
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值