1. Ehab and Path-etic MEXs
题意
给边上打0~n-2这n-1个标签,使得任意两点之间的路径标号的最大值最小。输出边上的标号。
思路
若存在度数大于等于3的点,任选一个度数大于三的点,任选其三条边标记上0,1,2,然后其他所有边随便标。
解释:
- 首先各点对的mex的最大值的最小值不能为0,因为至少有边权为0。
- 接着也不能为1,因为树是联通的,必然有一条路径包含0,1(任意选两个边,也会被某一条路径包含)。
- 所以我们尝试能不能让所求的值为2,发现只要0,1,2连接在同一个节点上,不可能有路径会同时经过0,1,2。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int maxn = 1e5+10;
int ans[maxn];
int n;
int vis[maxn];
PII a[maxn];
int main(){
cin>>n;
int from,to,pos = 0;
for(int i=1;i<n;i++){
cin>>from>>to;
vis[from] ++, vis[to] ++;
a[i].first = from, a[i].second = to;
if(! pos){
if(vis[from] >= 3)
pos = from;
if(vis[to] >= 3)
pos = to;
}
}
if(! pos){
for(int i=0;i<n-1;i++)
cout<<i<<' ';
cout<<endl;
}else{
int p = 0;
memset(ans, -1, sizeof(ans));
for(int i=1;i<n;i++){
if(a[i].first != pos && a[i].second != pos)
continue;
else{
ans[i] = p ++;
}
}
for(int i=1;i<n;i++){
if(ans[i] != -1)
continue;
else
ans[i] = p ++;
}
for(int i=1;i<n;i++){
cout<<ans[i]<<' ';
}
cout<<endl;
}
return 0;
}
2. WeirdSort
题意
给了两组数,第二组b[i]表示第一组的i和i+1可以交换位置,问可不可以把第一组数换成非降序数组。
思路
把根据b数组给a中的数一段一段排序。看最后是不是非降序。没必要用并查集,我自己没注意写成并查集了而已。
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdio>
const int maxn = 105;
typedef long long ll;
using namespace std;
int f[maxn],a[maxn];
int find(int x){
if(x != f[x])
f[x] = find(f[x]);
return f[x];
}
int init(){
for(int i=0; i<maxn; i++){
f[i] = i;
}
}
int main(){
int t; cin>>t;
while(t --){
int n,m;
cin>>n>>m;
init();
for(int i=1;i<=n;i++){
cin>>a[i];
}
int temp;
for(int i=1;i<=m;i++){
cin>>temp;
int p1 = find(temp);
int p2 = find(temp + 1);
if(p1 != p2){
f[p1] = p2;
}
}
for(int i=1, j=i + 1;i<=n && j <= n;i = j){
for(int p1 = find(i), p2 = find(j); j <= n && p1 == p2; j ++){
p1 = find(i), p2 = find(j);
if(!(j <= n && p1 == p2))
break;
}
sort(a+i,a+j);
}
int flag = 1;
for(int i=1;i<n;i++){
if(a[i] > a[i + 1]){
flag = 0;
break;
}
}
if(flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
3. 区间选点
题意
求给定的若干个区间内,每个区间内都有点的最少点数。
思路
贪心。
[假算法]先考虑按照左端点排序,在不能借助上一个点的情况下,在这一个区间的右端点新建一个点。
[真算法]按右端点排序,不能借助上一个点的情况下,在右端点新建一个点。
假算法为什么假呢。如图1,加算法会在粗红线建立一个点,而忽略了左下角的区间。真算法如图2。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <