Tom
首先,早香肠和晚香肠一定把树分成两个联通块,并且 与 联通
于是可以枚举 的边,看一下 的大小是不是 或
然后对于两边 一遍,需要让每一个点比它的儿子小,按 序编号即可
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 2e5 + 5;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)) { ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
return cnt * f;
}
int n, a, b;
int first[N], nxt[N], to[N], tot;
void add(int x, int y){ nxt[++tot] = first[x], first[x] = tot, to[tot] = y; }
int siz[N], du[N], col[N];
int fx, fy;
void dfs(int u, int fa){
siz[u] = 1;
for(int i = first[u]; i; i = nxt[i]){
int t = to[i]; if(t == fa) continue;
dfs(t, u); siz[u] += siz[t];
} if(siz[u] == a || siz[u] == b){ fx = fa; fy = u; }
}
int dfn[N], sign;
void Get(int u, int fa){
dfn[u] = ++sign;
for(int i = first[u]; i; i = nxt[i]){
int t = to[i]; if(t == fa) continue;
Get(t, u);
}
}
int flg = 0;
void calc(){
if(sign == a && !flg){ flg = 1;
for(int i = 1; i <= n; i++) if(dfn[i]) col[i] = a - dfn[i] + 1;
} else{
for(int i = 1; i <= n; i++) if(dfn[i]) col[i] = - (b - dfn[i] + 1);
}
}
int main(){
n = read(), a = read(), b = read();
for(int i = 1; i < n; i++){
int x = read(), y = read();
add(x, y); add(y, x); ++du[x]; ++du[y];
} dfs(1, 0);
if(!fx && !fy){ puts("-1"); return 0; }
sign = 0; memset(dfn, 0, sizeof(dfn)); Get(fx, fy); calc();
sign = 0; memset(dfn, 0, sizeof(dfn)); Get(fy, fx); calc();
for(int i = 1; i <= n; i++) cout << col[i] << " ";
return 0;
}
Jerry
好题啊!解法很多
首先有 的区间 , 表示区间 的最大,最小,枚举断点转移即可
对于每个数分开考虑,即考虑是加上它的贡献还是减去它的贡献
首先正数前面括号没有用,负数前面的括号可以让后面都反号
发现一个点取正取负只跟前面括号的奇偶性有关
表示到 ,有 个左括号的最优值,按奇偶性转移即可
考虑到只跟奇偶性有关,那么是不是可以把多个括号消成更少的括号使得与原来等价
发现一个性质:最多两层嵌套,可以感性理解,也可以手动拆一下括号
于是状态被压到了
如何转移,分类讨论,注意要用右括号消掉前端的左括号
:显然不能填括号
:强行钦定填一个左括号,如果本来不填括号也会被下一次右括号给消回去
#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)) { ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
return cnt * f;
}
cs int N = 2e5;
typedef long long ll;
int T, n; ll a[N];
int op[N];
ll f[N][3];
int main(){
T = read();
while(T--){
n = read();
a[1] = read(); op[1] = 1;
for(int i = 2; i <= n; i++){
char c = getchar();
if(c == '-') op[i] = -1;
else op[i] = 1;
a[i] = read();
}
f[0][0] = 0;
f[0][1] = f[0][2] = -1e18;
for(int i = 1; i <= n; i++){
if(op[i] == 1){
f[i][2] = f[i - 1][2] + a[i];
f[i][1] = max(f[i - 1][1] - a[i], f[i - 1][2] - a[i]);
f[i][0] = max(max(f[i - 1][0], f[i - 1][1]), f[i - 1][2]) + a[i];
}
if(op[i] == -1){
f[i][2] = max(f[i - 1][1] + a[i], f[i - 1][2] + a[i]);
f[i][1] = max(max(f[i - 1][0], f[i - 1][1]), f[i - 1][2]) - a[i];
f[i][0] = -1e18;
}
} cout << max(max(f[n][0], f[n][1]), f[n][2]) << '\n';
} return 0;
}
解法2:
首先 号连通块可以缩掉,于是分类讨论,只有以下 3 种情况
后面的对前面的没有影响,考虑令 表示 i 到最后的最大值
对于第一种情况,如果是 的话可以填成 ,如果是 的话,可以填成 ,对于 后面的同理,
对于第二种情况,考虑 填不填括号:
,同第一种,可以将后面的全部构造成正,
,
对于第三种情况,发现
#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)) { ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
return cnt * f;
}
cs int N = 2e5;
typedef long long ll;
int T, n; ll a[N];
int op[N];
ll f[N], sum[N];
int main(){
T = read();
while(T--){
n = read(); int cnt = 0;
a[++cnt] = read(); op[0] = 1;
for(int i = 2; i <= n; i++){
char c = getchar();
if(c == '-') op[cnt] = -1;
else op[cnt] = 1;
if(op[cnt] == 1 && op[cnt - 1] == 1) a[cnt] += read();
else a[++cnt] = read();
} sum[cnt + 1] = 0;
for(int i = cnt; i >= 1; i--) sum[i] = sum[i + 1] + a[i];
f[cnt] = a[cnt] * op[cnt - 1];
for(int i = cnt - 1; i >= 1; i--){
if(op[i - 1] == 1) f[i] = f[i + 1] + a[i];
else{
if(op[i] == -1) f[i] = -a[i] + sum[i + 1];
else f[i] = max(f[i + 1] - a[i], - a[i] - a[i + 1] + sum[i + 2]);
}
} cout << f[1] << '\n';
} return 0;
}
首先不会走回头路,也不会走得很上去或很下去,最优的走法一定是扒到边边走,过了这一个后延平行 轴的线直到碰到下一个,在延着下一个的边边走
如果令 表示 从 i 的上下端点走到终点的最短路
那么 只可能从沿着 x 走到的下一个转移过来,线段树维护一下下一个是什么
就是区间覆盖,单点插颜色
#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)) { ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
return cnt * f;
}
cs int N = 5e5 + 5;
int n, f[N][2], ed;
cs int inf = 1e9;
void Mi(int &a, int b){ if(a > b) a = b; }
struct matrix{
int a, b, c, d;
matrix(int _a = 0, int _b = 0, int _c = 0, int _d = 0){ a = _a; b = _b; c = _c; d = _d; }
}t[N];
vector<matrix> v[N];
int Dx[N << 1], sx, Dy[N << 1], sy;
struct segmentree{
int col[N << 3], tg[N << 3];
#define mid ((l+r)>>1)
void pushnow(int x, int v){ tg[x] = col[x] = v; }
void pushdown(int x){ if(tg[x]) pushnow(x<<1, tg[x]), pushnow(x<<1|1, tg[x]), tg[x] = 0; }
int ask(int x, int l, int r, int p){
if(l == r) return col[x]; pushdown(x);
if(p <= mid) ask(x << 1, l, mid, p);
else ask(x << 1 | 1, mid + 1, r, p);
}
void modify(int x, int l, int r, int L, int R, int v){
if(l == r) { pushnow(x, v); return; } pushdown(x);
if(L <= mid) modify(x << 1, l, mid, L, R, v);
if(R > mid) modify(x << 1 | 1, mid + 1, r, L, R, v);
}
int query(int x){ return ask(1, 1, sy, x); }
void ins(int l, int r, int v){ modify(1, 1, sy, l, r, v); }
}seg;
void Dic(){
sort(Dx + 1, Dx + sx + 1); sx = unique(Dx + 1, Dx + sx + 1) - (Dx + 1);
sort(Dy + 1, Dy + sy + 1); sy = unique(Dy + 1, Dy + sy + 1) - (Dy + 1);
for(int i = 1; i <= n; i++){
t[i].a = lower_bound(Dx + 1, Dx + sx +1, t[i].a) - Dx;
t[i].b = lower_bound(Dy + 1, Dy + sy +1, t[i].b) - Dy;
t[i].d = lower_bound(Dy + 1, Dy + sy +1, t[i].d) - Dy;
}
}
int main(){
freopen("speike.in","r",stdin);
freopen("speike.out","w",stdout);
n = read(); ed = read();
if(n == 0){ cout << ed << '\n'; return 0;}
for(int i = 1; i <= n; i++){
t[i].a = read(), t[i].b = read(), t[i].c = read(), t[i].d = read();
Dx[++sx] = t[i].a;
Dy[++sy] = t[i].b; Dy[++sy] = t[i].d;
if(t[i].a > t[i].c) swap(t[i].a, t[i].c);
if(t[i].b > t[i].d) swap(t[i].b, t[i].d);
}
Dy[++sy] = 0; Dic();
int fi = lower_bound(Dy + 1, Dy + sy + 1, 0) - Dy;
for(int i = 1; i <= n; i++) v[t[i].a].push_back(t[i]);
int idx = n;
for(int i = 1; i <= sx; i++){
int nx = idx;
for(int j = 0; j < v[i].size(); j++){
matrix now = v[i][j];
t[nx] = now;
int nxt = seg.query(now.d);
if(!nxt) f[nx][0] = ed - Dx[now.a] + abs(Dy[now.d]);
else{
f[nx][0] = f[nxt][0] + Dy[t[nxt].d] - Dy[now.d];
Mi(f[nx][0], f[nxt][1] + Dy[now.d] - Dy[t[nxt].b]);
f[nx][0] += Dx[t[nxt].a] - Dx[now.a];
}
nxt = seg.query(now.b);
if(!nxt) f[nx][1] = ed - Dx[now.a] + abs(Dy[now.b]);
else{
f[nx][1] = f[nxt][0] + Dy[t[nxt].d] - Dy[now.b];
Mi(f[nx][1], f[nxt][1] + Dy[now.b] - Dy[t[nxt].b]);
f[nx][1] += Dx[t[nxt].a] - Dx[now.a];
} --nx;
} nx = idx;
for(int j = 0; j < v[i].size(); j++){
matrix now = v[i][j];
seg.ins(now.b, now.d, nx);
--nx;
} idx = nx;
}
int ans = inf;
int nxt = seg.query(fi);
Mi(ans, Dx[t[nxt].a] + abs(Dy[t[nxt].b]) + f[nxt][1]);
Mi(ans, Dx[t[nxt].a] + abs(Dy[t[nxt].d]) + f[nxt][0]);
cout << ans; return 0;
}
火锅盛宴
考场真的是傻逼!
考场解法:对于一个食物,它熟的时间是 ,我的想法是把它插到线段树,维护区间
操作 1 就可以在线段树上二分,操作 2 就是线段树单点查,叶子结点维护一个 就可以了
操作 3 与 操作 0,1,2 独立,将操作 0,1,2 对 3 的影响,即插入删除一些权值为时间的点,然后查询区间权值 的个数, 解决,卡常只剩 分
打了 排
#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)) { ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
return cnt * f;
}
cs int N = 1e5 + 5;
cs int Q = 5e5 + 5;
cs int inf = 2e9;
int T;
int n, s[N];
int m;
int typ[Q];
int ans[Q];
struct data{
int op, Time, pos, id, typ;
data(int _op = 0, int t = 0, int p = 0, int i = 0, int _typ = 0){
op = _op; Time = t; pos = p; id = i; typ = _typ;
}
}q[Q << 1], A[Q << 1], B[Q << 1];
int tot, b[Q << 1];
bool cmpt(data a, data b){ return a.Time < b.Time; }
struct segmentree{
set<int> S[N << 2];
int mi[N << 2];
#define mid ((l+r)>>1)
int Get(int x){ if(S[x].size()) return *S[x].begin(); return inf; }
void build(int x, int l, int r){
mi[x] = inf; if(l == r){ S[x].clear(); return; }
build(x<<1, l, mid); build(x<<1|1, mid+1, r);
}
void pushup(int x){ mi[x] = min(mi[x<<1], mi[x<<1|1]); }
void modify(int x, int l, int r, int p, int v){
if(l == r){
S[x].insert(v);
mi[x] = Get(x);
return;
}
if(p <= mid) modify(x << 1, l, mid, p, v);
else modify(x << 1 | 1, mid+1, r, p, v);
pushup(x);
}
int qTime(int x, int l, int r, int Time){
if(l == r){
q[++tot] = data(1, *S[x].begin(), l, 0, -1);
S[x].erase(S[x].begin());
mi[x] = Get(x); return l;
}
int ans = 0;
if(mi[x << 1] <= Time) ans = qTime(x << 1, l, mid, Time);
else ans = qTime(x << 1 | 1, mid+1, r, Time);
pushup(x); return ans;
}
int askmi(int Time){ if(mi[1] > Time) return -1; return qTime(1, 1, n, Time); }
int qId(int x, int l, int r, int p, int Time){
if(l == r){
if(S[x].empty()) return -1;
if(*S[x].begin() <= Time){
q[++tot] = data(1, *S[x].begin(), l, 0, -1);
S[x].erase(S[x].begin());
mi[x] = Get(x);
return 0;
} return *S[x].begin() - Time;
}
int ans = 0;
if(p <= mid) ans = qId(x << 1, l, mid, p, Time);
else ans = qId(x << 1|1, mid+1, r, p, Time);
pushup(x); return ans;
}
int askid(int p, int Time){ return qId(1, 1, n, p, Time); }
#undef mid
}seg;
void Deal(){
for(int i = 1; i <= m; i++){
int Time = read(), op = read(); typ[i] = op;
if(op == 0){
int id = read();
seg.modify(1, 1, n, id, Time + s[id]);
q[++tot] = data(1, Time + s[id], id, i, 1);
}
if(op == 1){
ans[i] = seg.askmi(Time);
}
if(op == 2){
int id = read();
ans[i] = seg.askid(id, Time);
}
if(op == 3){
int l = read(), r = read();
q[++tot] = data(2, Time, l - 1, i, -1);
q[++tot] = data(2, Time, r, i, 1);
}
}
}
struct BIT{
int c[N];
void add(int x, int v){ for(;x<=n;x+=x&-x) c[x] += v;}
int ask(int x){ int ans = 0; for(;x;x-=x&-x) ans += c[x]; return ans;}
}bit;
void cdq(int l, int r){
if(l == r) return;
int mid = (l+r) >> 1;
int L = 0, R = 0;
for(int i = l; i <= mid; i++) if(q[i].op == 1) A[++L] = q[i];
for(int i = mid + 1; i <= r; i++) if(q[i].op == 2) B[++R] = q[i];
sort(A + 1, A + L + 1, cmpt);
sort(B + 1, B + R + 1, cmpt);
for(int i = 1, j = 1; j <= R; j++){
while(i <= L && A[i].Time <= B[j].Time){
bit.add(A[i].pos, A[i].typ);
++i;
}
ans[B[j].id] += B[j].typ * bit.ask(B[j].pos);
}
for(int i = 1; i <= L; i++) if(A[i].Time <= B[R].Time) bit.add(A[i].pos, -A[i].typ);
cdq(l, mid); cdq(mid + 1, r);
}
void Solve(){
n = read(); seg.build(1, 1, n);
for(int i = 1; i <= n; i++) s[i] = read();
m = read();
Deal();
cdq(1, tot);
for(int i = 1; i <= m; i++){
if(typ[i] == 1){
if(~ans[i]) cout << ans[i] << '\n';
else puts("Yazid is angry.");
}
if(typ[i] == 2){
if(ans[i] == 0) puts("Succeeded!");
else if(ans[i] == -1) puts("YJQQQAQ is angry.");
else cout << ans[i] << '\n';
}
if(typ[i] == 3) cout << ans[i] << '\n';
}
}
void Init(){
memset(ans, 0, sizeof(ans));
tot = 0;
}
int main(){
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
T = read();
while(T--) Solve(), Init();
return 0;
}
正解,考虑分别维护煮熟的和没有煮熟的集合
每次需要把新煮熟的插到煮熟的集合,就是把 的一些点插到另一个集合中
优先队列或者 维护
然后需要支持:
查最小的不为 0 的位置
查一个位置为不为 0
查区间的个数
删除,插入
树状数组,第一个类似倍增跳就好了
如果一个位置为 0,需要求没有熟的最小熟的时间,考虑到小的一定先出,用一个队列维护即可
每次弹优先队列的时候顺便弹一下
妥妥的签到题
#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)) { ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
return cnt * f;
}
cs int N = 1e5 + 5, Q = 5e5 + 5, inf = 2e9;
int T, n, s[N], m, ans[Q], typ[Q];
queue<int> q[N]; // 维护未熟的食物
struct node{
int id, Time; node(int i = 0, int t = 0){ id = i; Time = t; }
bool operator < (cs node &a) cs{ return Time > a.Time;}
}; priority_queue<node> S;
struct BIT{
int c[N];
void add(int x, int v){ for(;x<=n; x+=x&-x) c[x] += v; }
int askmi(){
int now = 0;
for(int i = 18; i >= 0; i--){
if(now + (1 << i) <= n && c[now + (1 << i)] == 0) now += (1 << i);
} if(now == n) return -1; add(now + 1, -1); return now + 1;
}
int ask(int x){ int ans = 0; for(;x;x-=x&-x) ans += c[x]; return ans; }
int askid(int x, int Time){
if(ask(x) - ask(x-1) == 0){ if(q[x].empty()) return -1; return q[x].front() - Time;}
add(x, -1); return 0;
}
}bit;
void Deal(){
for(int i = 1; i <= m; i++){
int Time = read(), op = read(); typ[i] = op;
while(!S.empty() && S.top().Time <= Time){ node x = S.top(); S.pop(); bit.add(x.id, 1); q[x.id].pop(); }
if(op == 0){ int id = read(); S.push(node(id, Time + s[id])); q[id].push(Time + s[id]); }
if(op == 1) ans[i] = bit.askmi();
if(op == 2){ int id = read(); ans[i] = bit.askid(id, Time); }
if(op == 3){ int l = read(), r = read(); ans[i] = bit.ask(r) - bit.ask(l - 1);}
}
}
void Solve(){
n = read(); for(int i = 1; i <= n; i++) s[i] = read(); m = read(); Deal();
for(int i = 1; i <= m; i++){
if(typ[i] == 1){ if(~ans[i]) cout << ans[i] << '\n'; else puts("Yazid is angry."); }
if(typ[i] == 2){
if(ans[i] == 0) puts("Succeeded!"); else if(ans[i] == -1) puts("YJQQQAQ is angry.");
else cout << ans[i] << '\n';
} if(typ[i] == 3) cout << ans[i] << '\n';
}
}
void Init(){
memset(ans, 0, sizeof(ans)); while(!S.empty()) S.pop();
for(int i = 1; i <= n; i++) while(!q[i].empty()) q[i].pop();
memset(bit.c, 0, sizeof(bit.c));
}
int main(){ T = read(); while(T--) Solve(), Init(); return 0; }
Polygon
送了
考虑不枚举 3 个点,枚举 2 的点 然后用一个啥数据结构快速得到最后一个点的最优位置
先除去这一条线自己就覆盖了的,就是一个端点在它们上面,两个在它们下面
用一个 存以它为端点的所有三角形,到它的时候插一下
考虑 挪到 有什么变化,以 为顶点且另外两个在 区间的会凉掉,去除
考虑另一个点 的位置会产生什么贡献,新增的那一个贡献就是对 端点为 的三角形,如果另两个端点 在 直接,那么对 有贡献,线段树区间加全局
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 1e3 + 5;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)) { ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
return cnt * f;
}
int n, ans;
typedef pair<int, int> pi;
#define mp make_pair
#define fi first
#define se second
#define pb push_back
vector<pi> v[N];
bool in(int a, int b, int c){ return a <= b && b <= c; }
void Mx(int &a, int b){ if(a < b) a = b; }
struct segmentree{
int mx[N << 2], tg[N << 2];
#define mid ((l+r)>>1)
void build(int x, int l, int r){
mx[x] = tg[x] = 0; if(l == r) return;
build(x<<1, l, mid); build(x<<1|1, mid+1, r);
}
void pushnow(int x, int v){ mx[x] += v; tg[x] += v; }
void pushdown(int x){ if(tg[x]) pushnow(x<<1, tg[x]), pushnow(x<<1|1, tg[x]), tg[x] = 0;}
void modify(int x, int l, int r, int L, int R, int v){
if(L<=l && r<=R){ pushnow(x, v); return; } pushdown(x);
if(L<=mid) modify(x<<1, l, mid, L, R, v);
if(R>mid) modify(x<<1|1, mid+1, r, L, R, v);
mx[x] = max(mx[x<<1], mx[x<<1|1]);
}
}seg;
void solve(int x){
int y = x + 1; seg.build(1, x, n);
int now = 0;
while(y + 1 <= n){
for(int i = 0; i < v[y].size(); i++){
pi t = v[y][i];
if(!in(x + 1, t.fi, y - 1) && !in(x + 1, t.se, y - 1)) ++now;
} ++y;
for(int i = 0; i < v[y].size(); i++){
pi t = v[y][i];
if(in(x, t.fi, y - 1) && in(x, t.se, y - 1)){
--now;
seg.modify(1, x, n, t.fi + 1, y - 1, 1);
}
} Mx(ans, now + seg.mx[1]);
}
}
int main(){
n = read();
for(int i = 1; i <= n - 2; i++){
int a[3];
for(int j = 0; j < 3; j++) scanf("%d", &a[j]), ++a[j];
sort(a, a + 3);
v[a[0]].pb(mp(a[1], a[2]));
v[a[1]].pb(mp(a[0], a[2]));
v[a[2]].pb(mp(a[0], a[1]));
} for(int i = 1; i <= n - 2; i++) solve(i);
cout << ans << '\n'; return 0;
}
有一个结论,就是面与面有公共边则连边,有点像对偶图,那么最后连出来是一棵树
并且两点直接穿过的边对应这树上的路径,画个图发现比较显然
然后 3 跳边的路径对应树上的一个三叉路径,树形 求即可
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 1e3 + 5;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)) { ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
return cnt * f;
}
int n, ans, now;
int first[N], nxt[N << 1], to[N << 1], tot;
void add(int x, int y){nxt[++tot] = first[x], first[x] = tot, to[tot] = y; }
typedef pair<int, int> pi;
#define mp make_pair
map<pi, int> m;
int d[N];
void dfs1(int u, int fa){
for(int i = first[u]; i; i = nxt[i]){
int t = to[i]; if(t == fa) continue;
dfs1(t, u); d[u] = max(d[u], d[t]);
} ++d[u];
}
void dfs2(int u, int fa, int val){
int mx = 0, mxi = 0;
for(int i = first[u]; i; i = nxt[i]){
int t = to[i]; if(t == fa) continue;
if(d[t] > mx){ mxi = mx; mx = d[t]; }
else if(d[t] > mxi) mxi = d[t];
} ans = max(ans, mx + mxi + val + 1);
for(int i = first[u]; i; i = nxt[i]){
int t = to[i]; if(t == fa) continue;
if(d[t] != mx) dfs2(t, u, max(val, mx) + 1);
else dfs2(t, u, max(val, mxi) + 1);
}
}
int main(){
n = read();
for(int i = 1; i <= n - 2; i++){
now++;
int a[3]; scanf("%d%d%d", &a[0], &a[1], &a[2]);
sort(a, a + 3);
for(int j = 0; j <= 2; j++)
for(int k = j + 1; k <= 2; k++)
if(m.count(mp(a[j], a[k]))){
add(now, m[mp(a[j], a[k])]);
add(m[mp(a[j], a[k])], now);
}
for(int j = 0; j <= 2; j++)
for(int k = j + 1; k <= 2; k++)
m[mp(a[j], a[k])] = now;
} dfs1(1, 0); dfs2(1, 0, 0); cout << ans;
return 0;
}
来源:https://blog.csdn.net/sslz_fsy/article/details/102731760