所有可达路径上最大值的最小值
有点最小生成树的味道
例题 1:
2020牛客NOIP赛前集训营-提高组(第三场)B
解题报告:
1.
1.
1. 图论问题 ,依题发现牛半仙每走完一遍后它的接受程度会递增,也就说之前走过的还会被下一次重复走,正面不好计算,那我们不妨考虑到达每种类型妹子的最小困难程度,再考虑其贡献。
2.
2.
2. 怎么求每条路径上最大值的最小值呢 ??会发现对每条路径的限制就是路径上最大困难程度,显然变成了最小生成树问题(因为可以保证最大值尽量最小)。找到最小生成数之后,以
x
x
x 为根节点进行树遍历,维护处到达每个点的最小接受程度和达到每种类型妹子的最小困难程度。
3.
3.
3. 因为妹子类型
<
=
600
<=600
<=600 所以直接枚举每种类型的妹子考虑其贡献,记得
l
o
n
g
l
o
n
g
long long
longlong。
代码展示:
#include<bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 5e5 + 5;
const int MOD = 1e9 + 7;
inline int read() {
int s = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {s = (s << 1) + (s << 3) + ch - '0'; ch = getchar();}
return s * f;
}
inline void write(LL x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
struct TMD {
int to,next,w;
} edge[maxn<<1];
int head[maxn],cnt,knt,n,q,x,opt,m,mod,f[maxn],dis[maxn];
pii t[maxn];
int c[maxn],col[605];
bool vis[maxn];
void add(int from,int to,int w) {
edge[++cnt]={to,head[from],w};head[from]=cnt;
}
struct node{
int u,v,w;
node(){}
node(int _u,int _v,int _w){
u=_u,v=_v;w=_w;
}
}p[maxn];
bool cmp(node A,node B) {return A.w<B.w;}
int getfind(int x){
return x==f[x]?x:f[x]=getfind(f[x]);
}
void kruskal(){
for(int i=1;i<=n;i++) f[i]=i;
sort(p+1,p+m+1,cmp);
int k1,k2,cnt=1;
for(int i=1;i<=m;i++){
k1=getfind(p[i].u);
k2=getfind(p[i].v);
if(k1!=k2){
f[k2]=k1;
cnt++;
add(p[i].u,p[i].v,p[i].w);
add(p[i].v,p[i].u,p[i].w);
}
if(cnt==n) break;
}
}
void dfs(int now,int fa){
col[c[now]]=min(col[c[now]],dis[now]);
for(int i=head[now];i;i=edge[i].next){
int to=edge[i].to,w=edge[i].w;
if(to==fa) continue;
dis[to]=max(dis[now],w);
dfs(to,now);
}
}
void solve(){
kruskal();
for(int i=1;i<=600;i++) col[i]=INT_MAX;
dfs(x,-1);
}
LL query(int l,int r){
LL ans=0;
for(int i=1;i<=600;i++){
if(col[i]==INT_MAX||col[i]>r) continue;
if(col[i]<=l) ans+=r-l+1;
else ans+=r-col[i]+1;
}
return ans;
}
int main() {
int u,v,w,l,r;
n=read();m=read();q=read();x=read();opt=read();
if(opt==1) mod=read();
for(int i=1;i<=n;i++) c[i]=read();
for(int i=1;i<=m;i++){
u=read();v=read();w=read();
p[i]=node(u,v,w);
}
solve();
LL ans=0;
for(int i=1;i<=q;i++){
l=read();r=read();
if(opt==1){
l=(l^ans)%mod+1;r=(r^ans)%mod+1;
}
if(l>r) swap(l,r);
write(ans=query(l,r));
putchar('\n');
}
return 0;
}
所有可达路径上最小值的最大值
有点最大生成树的味道
例题1:
POJ1797
例题2: