2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问。他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色。为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于 10^5105 的字符串。现在魔法师想要通过一系列魔法使得这两个字符串相同。每种魔法形如 (u,\ v),\ u,\ v \le 10^5(u, v), u, v≤105,可以将一个字符 uu改成一个字符 vv,并且可以使用无限次。出于种种原因,魔法师会强行指定这两个串能否进行修改。

若失败输出 -1?1,否则输出最少使用的魔法的种类数。

输入格式

一个正整数 n(n \le 10^5)n(n≤105) 表示每个字符串的长度。

接下来两行每行首先输入一个单词("Variable""Constant"),"Variable"表示这个字符串能进行修改,"Constant"表示这个字符串不能进行修改,然后 nn 个正整数表示一个字符集不大于 10^5105 的字符串。

输出格式

若有解,输出一个自然数表示最少使用的魔法的种类数。否则输出 -1?1。

保证所有输入的数字都为正整数且不大于 10^5105。

样例输入1

2
Constant 111 222
Variable 222 111

样例输出1

2

样例输入2

2
Variable 111 222
Variable 222 111

样例输出2

1

题目来源

2018 计蒜之道 复赛



不说了 SB错误能卡我好久。

对于cc的情况判字符串是不是相等。

对于vv的情况并查集找联通块数,次数就是总点数减去联通块数。

对于cv的情况我们仍旧双向存联通块。对于内部有自环的我们建的边数等于块内点数。对于没有自环的,我们建的边数等于块内点数-1。

第二种情况跟vv的是类似的,第一种情况则是把所有点建成一个大的自环,这样所有点都互相可达了。

  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define INF 0x3f3f3f3f
  5 #define LL long long
  6 #define pb push_back
  7 #define mod 1000000007
  8 #define ls(i) (i<<1)
  9 #define rs(i) (i<<1|1)
 10 #define mp make_pair
 11 #define fi first
 12 #define se second
 13 using namespace std;
 14 const int N=1e5+10;
 15 const int P=1e5;
 16 int inf[2];
 17 int s[2][N];
 18 vector<int> e[N];
 19 bool vis[N],ins[N];
 20 bool ct[N];
 21 int fa[N];
 22 bool exist[N];
 23 int now,ans;
 24 char is[20];
 25 bool dfs(int u)
 26 {
 27     ins[u]=1;
 28     vis[u]=1;
 29     int flag=0;
 30     for(auto p:e[u])
 31     {
 32         if(ins[p])
 33         {
 34             flag=1;
 35             continue;
 36         }
 37         if(vis[p])
 38             continue;
 39         if(dfs(p)) flag=1;
 40     }
 41     ins[u]=0;
 42     return flag;
 43 }
 44 int Find(int x) {return fa[x]==x?x: fa[x]=Find(fa[x]);}
 45 void Union(int u,int v)
 46 {
 47     int x=Find(u),y=Find(v);
 48     if(x!=y)
 49         fa[x]=y;
 50     return ;
 51 }
 52 int main()
 53 {
 54     int n;
 55     scanf("%d",&n);
 56     for(int i=0;i<2;i++)
 57     {
 58         scanf("%s",is);
 59         if(strcmp(is,"Constant")==0)
 60             inf[i]=0;
 61         else
 62             inf[i]=1;
 63         for(int j=1;j<=n;j++)
 64             scanf("%d",&s[i][j]);
 65     }
 66     if(inf[0]==0)
 67         now=1;
 68     else
 69         now=0;
 70     int pt=inf[0]+inf[1];
 71     for(int i=1;i<=P;i++)
 72         fa[i]=i;
 73     for(int i=1;i<=n;i++)
 74     {
 75         if(pt>=1 && s[now][i]!=s[now^1][i])
 76             e[s[now][i]].pb(s[now^1][i]),Union(s[now][i],s[now^1][i]);
 77         exist[s[now][i]]=1;
 78         exist[s[now^1][i]]=1;
 79     }
 80     ans=0;
 81     for(int i=1;i<=P;i++)
 82     {
 83         if(e[i].size()>0)
 84         {
 85             sort(e[i].begin(),e[i].end());
 86             e[i].resize(unique(e[i].begin(),e[i].end())-e[i].begin());
 87         }
 88         if(exist[i]) ans++;
 89     }
 90     if(pt==0)
 91     {
 92         bool flag=0;
 93         for(int i=1;i<=n;i++)
 94             if(s[0][i]!=s[1][i])
 95                 flag=1;
 96         if(flag)
 97             printf("-1\n");
 98         else
 99             printf("0\n");
100     }
101     if(pt==1)
102     {
103         for(int i=1;i<=P;i++)
104             if(exist[i] && !vis[i])
105                 if(dfs(i)) ct[Find(i)]=1;
106         for(int i=1;i<=P;i++)
107             if(exist[i] && fa[i]==i && ct[i]==0)
108                 ans--;
109         printf("%d\n",ans);
110     }
111     if(pt==2)
112     {
113         for(int i=1;i<=P;i++)
114             if(exist[i] && fa[i]==i)
115                 ans--;
116         printf("%d\n",ans);
117     }
118     return 0;
119 }

原文地址:https://www.cnblogs.com/wujiechao/p/9194150.html

时间: 2024-10-09 19:52:23

2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)的相关文章

贝壳找房魔法师顾问[并查集+DAG判断]

题目链接[https://nanti.jisuanke.com/t/27647] //计蒜客2018复赛D题,想简单了. 题解: 题目是中文的,不再赘述. 题解: 分为三种情况:1.两个字符串都不能变:这种情况最简单,直接暴力判断两个支付穿是否相同即可. 2.两个字符串都能变:把上下对应位置不同的点连无向边(因为都可以改变),建立了一个深林,这里用并查集实现,顺便维护每个联块的大小,对于每个联通块来说,要把这些点都变成一样的,最少要变换(size-1)次,即选出一个点,把其他的点都变成被选中的点

2018 计蒜之道 复赛

A. 贝壳找房函数最值 常规贪心推式子.按(a-1)/b排序 #include <bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;++i) #define frep(i,a,b) for(int i=a;i>=b;--i) #define mem(W) memset(W,0,sizeof(W)) #define pb push_back typedef long long ll; const int N = 1e5+100; c

贝壳找房魔法师顾问 2018 计蒜之道 复赛

https://nanti.jisuanke.com/t/A1725 V&V 无向图 强连通图 每个子图,n个点,选择n-1条,使互相连接 因为目标点x->点y,可以改为点y->点x V&C 弱连通图(将有向图的所有的有向边替换为无向边,所得到的图称为原图的基图.如果一个有向图的基图是连通图,则有向图是弱连通图.) 1.一个弱连通子图,它里面的点与该弱连通子图外的点与没有关系,可以单独处理 2.弱连通子图里,一个点,必有另外点与之相邻,包括入和出 3.若弱连通子图里有环,则无论

2018计蒜之道复赛

A 分析 mgj,自己都写出来了,硬是看了半天才写出来 考虑两个函数 ax+b , cx+d,两个函数的先后顺序影响的值有哪些即可,结构体排序即可 B Summary: 菜就应该打不到衣服 原文地址:https://www.cnblogs.com/Deadline/p/9196237.html

2018 计蒜之道 初赛 第三场

A. 贝壳找房性价比 题解:按s排序后,斜率最大的点必定在相邻的两点之间. #pragma warning(disable:4996) #include<queue> #include<map> #include<string> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #de

2018 计蒜之道 初赛 第五场

这次的比赛没有现场打,而是等到了今天才来补. 主要是因为那时候和HHHOJ上的比赛冲突了,所以就没写. 这次前三题的难度都比较低,但是就是一个T4要莫比乌斯反演.又是不可食用的. 好了我们开始看题. A. 贝壳找房搬家 这道题刚开始看的时候没看懂题意,觉得T1就是这种立体几何的题目,有种想死的感觉. 因为我认为这个方块可以不规则地想怎么放就怎么放的,其实题目中有一句话: 我们可以把这堆箱子看成一个\(x \times y \times z\) 的长方体. 什么?刚开始只能是长方体吗?好吧好像还是

2019 计蒜之道 复赛 E. 撑起信息安全“保护伞” (贪心,构造,规律)

为了给全球小学员打起信息安全"保护伞",VIPKID 还建立了一套立体化的安全防御体系,7 \times 247×24 小时持续安全监控与应急响应等多项联动,具备业界最高级别的数据安全保护标准.值得一提的是,VIPKID 也是行业业内唯一通过 ISO 国际信息安全体系认证.公安部信息安全等级保护三级认证的教育企业. 现在安全防御体系就检测到了一个小问题,需要你来帮忙解决其中有关"前驱与后继"的这一部分,让我们一起来守护小学员们的信息安全吧!请看题: 对于两个长度相等

计蒜之道复赛 B D F

B题是一个简单的模拟 求一下两个点中间在上deta的整数点 然后更新一下每个点的最后一次经过就好了 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug(x) cerr<<#x<<"=="<<(x)<<endl 4 using namespace std; 5 6 const int maxn=300+10; 7 8

(状压dp)2017 计蒜之道 复赛 F. 腾讯消消乐

腾讯推出了一款益智类游戏--消消乐.游戏一开始,给定一个长度为 nn 的序列,其中第 ii 个数为 A_iA?i??. 游戏的目标是把这些数全都删去,每次删除的操作为:选取一段连续的区间,不妨记为 [L,R][L,R],如果这一段区间内所有数的最大公约数 \geq k≥k(kk 值在游戏的一开始会给定),那么这一段区间就能被直接删去. 注意:一次删除以后,剩下的数会合并成为一个连续区间. 定义 f(i)f(i) 为进行 ii 次操作将整个序列删完的方案数. 你需要实现一个程序,计算 \sum_{