题目描述

> “舔狗舔狗,
> 舔到最后,
> 一无所有。”

有 n 只舔狗,每只舔狗的心中都有自己朝思暮想的一位。

每个人虽然受到了一万次拒绝,还毅然第一万零一次鼓起勇气。

作为一个不食人间烟火的算法设计师,你早已看破红尘。但是,人世间的苦难仍让你挂念。看到众生在单恋中苦苦坚持,你决定普度众生,给大家找到一个最好的结局,让一无所有的舔狗尽量地少,让每个人都尽量能和自己喜欢的或喜欢自己的人修成正果。

也就是说,你需要给这 n 只舔狗配对,对于舔狗 i,他可以和他朝思暮想的人 aiai 配对。另外,喜欢 i 的其他舔狗也可以和他配对。你需要让没有被配对的舔狗尽量少。

输入描述:

第一行一个 n,表示舔狗个数。
第二行 n 个数字,第 i 个数字表示第 i只舔狗的朝思暮想的一位的编号 aiai。
2≤n≤1062≤n≤106

输出描述:

第一行一个数字,表示一无所有的舔狗的最小数量。

题目链接
就是一个无向图,问的是两两相邻的点匹配,最少会留下多少个没有匹配的点?
简单的分析一下,不难发现,我们可以看度,遇到度为1的点,那么在最贪心的选择,我们必须要去选择那个与它相邻的节点,同时,我们选了相邻的节点之后,要再把该节点所对出去的所有的点的度去更新了“-1”。然后,我们发现因为边的个数是N条,所以有可能存在环的。
怎么处理环的问题呢?我们可以用并查集,那些无法被访问到的节点一定是在环内的,所以我们在这里用到了并查集来维护一下,就可以维护那些在一个环内的个数,匹配数根据它的奇偶有关。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e6 + ;
int N, a[maxN], head[maxN], cnt, du[maxN], num[maxN], ans, root[maxN], sum[maxN], all[maxN];
int fid(int x) { return x == root[x] ? x : (root[x] = fid(root[x])); }
inline void mix(int x, int y)
{
int u = fid(x), v = fid(y);
if(u ^ v)
{
root[u] = v;
sum[v] += sum[u];
}
}
bool vis[maxN], used[maxN];
struct Eddge
{
int nex, to;
Eddge(int a=-, int b=):nex(a), to(b) {}
}edge[maxN<<];
inline void addEddge(int u, int v)
{
edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
queue<int> Q;
inline void tuopu()
{
while(!Q.empty())
{
int u = Q.front();
Q.pop();
if(vis[u]) continue;
vis[u] = true;
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(vis[v]) continue;
// du[v]--;
// if(du[v] == 1)
// {
// vis[v] = true;
// Q.push(v);
// num[v] = num[u] ^ 1;
// }
ans++; vis[v] = true;
for(int j=head[v], kk; ~j; j=edge[j].nex)
{
kk = edge[j].to;
if(!vis[kk])
{
du[kk]--;
if(du[kk] == )
{
//vis[kk] = true;
Q.push(kk);
}
}
}
break;
}
}
}
inline void init()
{
cnt = ans = ;
memset(head, -, sizeof(head));
memset(vis, false, sizeof(vis));
memset(num, , sizeof(num));
memset(used, false, sizeof(used));
memset(du, , sizeof(du));
memset(a, , sizeof(a));
memset(all, , sizeof(all));
for(int i=; i<=N; i++) { sum[i] = ; root[i] = i; }
while(!Q.empty()) Q.pop();
}
int main()
{
scanf("%d", &N);
init();
for(int i=, v; i<=N; i++)
{
scanf("%d", &v);
a[i] = v;
if(a[v] == i) continue;
du[i]++; du[v]++;
_add(i, v);
mix(i, v);
}
if(N == ) { printf("%d\n", ); return ; }
for(int i=; i<=N; i++)
{
if(du[i] == )
{
//vis[i] = true;
Q.push(i);
}
}
tuopu();
ans <<= ;
for(int i=; i<=N; i++)
{
int u = fid(i);
// if(!vis[i] && !used[u])
// {
// ans += ((int)(sum[u]/2)) * 2;
// used[u] = true;
// }
if(!vis[i]) all[u]++;
}
for(int i=; i<=N; i++) ans += ((int)(all[i]/)) * ;
printf("%d\n", N - ans);
return ;
}
/*
6
4 1 1 5 6 4
ans = 2
*/

 

舔狗【2019河北省大学生程序设计竞赛 J题】的更多相关文章

  1. 2019河北省大学生程序设计竞赛(重现赛)J-舔狗 (拓扑排序)

    题目链接:https://ac.nowcoder.com/acm/contest/903/J 题意:给你 n 个舔狗和他喜欢的人,让你俩俩配对(只能和喜欢它的和它喜欢的),求剩下的单身狗数量. 思路: ...

  2. 2019河北省大学生程序设计竞赛(重现赛) L题-smart robot(深度优先搜索)

    题目链接:https://ac.nowcoder.com/acm/contest/903/L 题意:给你 n * n的方阵,你可以从任意一个数字开始走,可以走上下左右四个方向,走过的数字会被拼合,拼合 ...

  3. 2019河北省大学生程序设计竞赛(重现赛)B 题 -Icebound and Sequence ( 等比数列求和的快速幂取模)

    题目链接:https://ac.nowcoder.com/acm/contest/903/B 题意: 给你 q,n,p,求 q1+q2+...+qn 的和 模 p. 思路:一开始不会做,后面查了下发现 ...

  4. hdu6489 2018 黑龙江省大学生程序设计竞赛j题

    Problem Description Kayaking is playing a puzzle game containing n different blocks. He marks the bl ...

  5. 2013年山东省第四届ACM大学生程序设计竞赛J题:Contest Print Server

    题目描述     In ACM/ICPC on-site contests ,3 students share 1 computer,so you can print your source code ...

  6. 2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛(8/11)

    $$2019中国大学生程序设计竞赛(CCPC)\ -\ 网络选拔赛$$ \(A.\hat{} \& \hat{}\) 签到,只把AB都有的位给异或掉 //#pragma comment(lin ...

  7. [BFS,A*,k短路径] 2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛 path (Problem - 6705)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=6705 path Time Limit: 2000/2000 MS (Java/Others)    Mem ...

  8. [贪心,dp] 2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛 Fishing Master (Problem - 6709)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=6709 Fishing Master Time Limit: 2000/1000 MS (Java/Othe ...

  9. ZZUOJ-1195-OS Job Scheduling(郑州大学第七届ACM大学生程序设计竞赛E题)

    1195: OS Job Scheduling Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 106  Solved: 35 [id=1195&quo ...

随机推荐

  1. [Codeforces 1201D]Treasure Hunting(DP)

    [Codeforces 1201D]Treasure Hunting(DP) 题面 有一个n*m的方格,方格上有k个宝藏,一个人从(1,1)出发,可以向左或者向右走,但不能向下走.给出q个列,在这些列 ...

  2. 网页中<a>标签新窗口和location.href 新窗口打开

    在网页制作过程中,经常遇到新窗口打开,一般是a超级链接或者location.href 新窗口打开形式,下面分别讲述两种之间的不同方式 1,a标签 新窗口 添加属性 target="_blan ...

  3. Java Collection总结

    继续啊啊啊啊啊啊 7. collection基本用法 Collection: add(obj) remove(obj) size() isEmpty() contains(obj) iterator( ...

  4. 移动端300ms延迟原理,穿透、遮罩层滑动导致下面滑动总结

    遮罩层滑动导致下面滑动 1,阻止弹层滑动,使用默认事件,使用这种方式弹层不能滑动 document.getElementById("model").addEventListener ...

  5. 树——minimum-depth-of-binary-tree(二叉树的最小深度)

    问题: Given a binary tree, find its minimum depth.The minimum depth is the number of nodes along the s ...

  6. leetcode x进制数 python3

    不少题目都是实现吧10进制数转换成x进制数,实际上都是一个套路,下面是7进制的,想换成什么进制,把7替换成相应数字即可,输出的是字符串 16,32进制这种有特殊要求的转不了,其他的应该通用 class ...

  7. [SDOI2015]寻宝游戏(LCA,set)

    [SDOI2015]寻宝游戏 题目描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到 ...

  8. VPS 安装MySQL

    目前Centos下默认支持的数据库是MariaDB,MariaDB是mysql的增强版本,由于mysql被Oracle收购之后,mysql之父担心之后mysql会变成闭源的软件,就又开发了这个版本,支 ...

  9. stream benchmark 交叉编译 on psoc

    之前有研究过这个,居然忘记了,看来确实是老了,没有盘过来. 如何下载,见 linux下载网页上的文件夹以及删除文件(stream) 出现了好几个问题 1. error while loading sh ...

  10. java并发学习--第四章 JDK提供的线程原子性操作工具类

    在了解JDK提供的线程原子性操作工具类之前,我们应该先知道什么是原子性:在多线程并发的条件下,对于变量的操作是线程安全的,不会受到其他线程的干扰.接下来我们就学习JDK中线程的原子性操作. 一.CAS ...