I题 Interesting Computer Game.
题意:
T组测试数据,每组输入一个n,然后输入n行,每行输入a b,可以选这两个数中没有选过的数,最多能选几个数。
思路:数据范围1e9,先离散化,起初每个数分别处于一个集合,输入a和b之后,如果a和b不相等,就合并a和b的集合,如果相等,就相当于自环,答案等于每个集合min(边数,点数) 之和。
并查集主要就是路径压缩和集合合并
#include <bits/stdc++.h>
#include <tr1/unordered_map>
#define ll long long
#define T int t;scanf("%d", &t);while(t--)
using namespace std;
using namespace std::tr1;
const int mod = 1e9 + 7;
const int maxn = 5e5 + 5;
unordered_map<int,int> mp; //每个数的集合
pair<int,int> pp[maxn];
int cnt[maxn]; //集合中点数量
int cnt_e[maxn]; //集合中边数量
int father[maxn]; //根节点
int num[maxn]; //数字
int find(int u){ //并查集路径压缩
if(father[u] == u) return u;
return father[u] = find(father[u]);
}
void bind(int u,int v){ //合并集合
int x = find(u);
int y = find(v);
father[x] = y;
}
int main(){
int cc = 1;
T{
int n;
scanf("%d", &n);
int cnt_n = 0;
mp.clear(); //别忘记清零
for(int i = 1; i <= n; i ++){
int a,b;
scanf("%d %d", &a, &b);
pp[i] = make_pair(a,b); //存输入的a b
num[++cnt_n] = a;
num[++cnt_n] = b;
}
sort(num+1,num+cnt_n+1); //先排序,后去重
cnt_n = (int)(unique(num+1,num+1+cnt_n)-(num + 1)); //离散化去重
for(int i = 1; i <= cnt_n; i ++){ //初始化数组
father[i] = i; //每个点自己是自己的祖先
cnt[i] = 1; //每个集合只有一个点
cnt_e[i] = 0; //每个集合没有边
}
for(int i = 1; i <= cnt_n; i ++)
mp[num[i]] = i; //每个数处于不同集合
for(int i = 1; i <= n; i ++){
int u = mp[pp[i].first];
int v = mp[pp[i].second];
u = find(u);
v = find(v);
int nu = cnt[u];
int nv = cnt[v];
int eu = cnt_e[u];
int ev = cnt_e[v];
bind(u,v); //合并u和v的集合
int k = find(u); //找到合并之后的集合编号
cnt[u] = 0; //合并之后原集合点清零
cnt[v] = 0;
if(u != v) cnt[k] = nu + nv; //如果集合不相同,新集合点数等于原集合点数之和
else cnt[k] = nu;
cnt_e[u] = 0;
cnt_e[v] = 0;
if(u != v) cnt_e[k] = eu + ev; //如果集合不相同,新集合边数等于原集合边数之和
else cnt_e[k] = eu;
cnt_e[k] ++; //不管怎么样,边数肯定要+1
}
ll ans = 0;
for(int i = 1; i <= cnt_n; i ++) //遍历每个集合
ans += min(cnt[i],cnt_e[i]);
printf("Case #%d: %lld\n",cc ++,ans);
}
return 0;
}
撒比题.
代码---------------------------->>>>>>
#include <bits/stdc++.h>
#define ll long long
#define T int t;scanf("%d", &t);while(t--)
using namespace std;
const int mod = 1e9 + 7;
int check(string s1[],string s2[],string s3[]){
for(int i = 0; i < 4; i ++){
if(s1[i]=="*" || s2[i]=="*" || s3[i]=="*") continue;
if(s1[i]!=s2[i] && (s1[i]==s3[i] || s2[i]==s3[i])) return 0;
if(s1[i]!=s3[i] && (s1[i]==s2[i] || s2[i]==s3[i])) return 0;
if(s2[i]!=s3[i] && (s1[i]==s3[i] || s1[i]==s2[i])) return 0;
}
return 1;
}
int main(){
int cc = 1;
T{
string ss[1005][5];
int n;
scanf("%d", &n);
string s;
for(int i = 1; i <= n; i ++){
cin>>s;
int cnt = 0;
for(int j = 0; j < s.length(); j ++){
if(s[j]=='[') continue;
if(s[j]==']'){
cnt++;
continue;
}
ss[i][cnt] += s[j];
}
}
int f = 0;
for(int i = 1; i <= n; i ++){
for(int j = i + 1; j <= n ; j ++){
for(int k = j + 1; k <= n; k ++){
if(check(ss[i], ss[j], ss[k])){
printf("Case #%d: %d %d %d\n",cc ++, i,j,k);
f = 1;
break;
}
}
if(f) break;
}
if(f) break;
}
if(f==0) printf("Case #%d: -1\n", cc ++);
}
return 0;
}