[codeforces 1296F] Berland Beauty 难在题意的理解+树上暴力+map的耗时,可不是O(1)
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址https://codeforces.com/contest/1296/problem/F
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
F - Berland Beauty | GNU C++11 | Accepted | 904 ms | 300 KB |
//题意怎么读都读不懂,看了此文https://blog.csdn.net/weixin_42429718/article/details/104199284才明白
/*
(注意是路径上的最小值,看了好久的题,比如1到3路径最小值是3 假如2到3为3,但是1到2可以为5 满足1到3路径最小值为3! ) 这句话理解清楚了这个题就不是很难了
*/
样例解释如下
若某条轨道没有涉及,那么该轨道美景在[1,1000000]均可。Otherwise, print n−1 integers f1,f2,…,fn−1 (1≤fi≤106),
思路:
因为n只有5000,算法的时间复杂度O(n^2),所以对于每一个限制条件,我们都在路径上保存一下这条边的最大边权,然后我们记录一下这个限制条件中路径上经过的边的编号
最后再check一遍m次限制路径上的边权的最小值是否等于w即可
以下代码,参考了https://www.e-learn.cn/content/qita/3369013关键点,记录轨道时,同时记录轨道的位次。
#include <cstdio>
#define maxn 5010
using namespace std;
int n,m,head[maxn],tot,val[maxn],vis[maxn],d,flag,u[maxn],v[maxn],w[maxn],check;//val[]记录铁路美景
struct node{
int to,next,seq;
}e[maxn*2];
void add_edge(int u,int v,int seq){
tot++,e[tot].to=v,e[tot].seq=seq,e[tot].next=head[u],head[u]=tot;
}
int max(int a,int b){
return a>b?a:b;
}
void dfs(int x,int w,int now){//从节点x开始遍历树。设置铁路美景值
int v,b;
vis[x]=now;
if(x==d){//找到终点d
flag=1;
return;
}
for(b=head[x];b;b=e[b].next){
v=e[b].to;
if(!flag&&vis[v]!=now){
dfs(v,w,now);
if(flag){
int pos=e[b].seq;
val[pos]=max(val[pos],w);
}
}
}
}
void judge(int x,int w,int now){//排查设置值 是否与 询问值 一致
int v,b;
vis[x]=now;
if(x==d){//找到终点d
flag=1;
return;
}
for(b=head[x];b;b=e[b].next){
v=e[b].to;
if(!flag&&vis[v]!=now){
judge(v,w,now);
if(flag){
int pos=e[b].seq;
if(val[pos]==w)check=1;
}
}
}
}
int main(){
int i,a,b,l,r;
scanf("%d",&n);
for(i=1;i<=n-1;i++){
scanf("%d%d",&a,&b);
add_edge(a,b,i),add_edge(b,a,i);
}
scanf("%d",&m);
for(i=1;i<=m;i++){//设置值
scanf("%d%d%d",&u[i],&v[i],&w[i]);
flag=0,d=v[i],dfs(u[i],w[i],i);
}
for(i=1;i<=m;i++){//检验
flag=0,check=0,d=v[i],judge(u[i],w[i],i+m);
if(check==0)break;
}
if(check==0)printf("-1\n");
else{
for(i=1;i<=n-1;i++)
if(val[i]==0)val[i]=1;//至少得是1. 1<=fi<=10^6
printf("%d",val[1]);
for(i=2;i<=n-1;i++)printf(" %d",val[i]);
printf("\n");
}
return 0;
}
//纯暴力,写得不好的代码,留存,以作纪念。
//Time limit exceeded on test 271 到这,应该可以完成使命了。
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
F - Berland Beauty | GNU C++11 | Time limit exceeded on test 271 | 3000 ms | 700 KB |
明白了一点,map的耗时,可不是O(1).
//纯暴力,写得不好的代码,留存,以作纪念。
//Time limit exceeded on test 271 到这,应该可以完成使命了。
#include <cstdio>
#include <map>
#define maxn 5010
using namespace std;
int n,m,head[maxn],tot,val[maxn],vis[maxn],d,flag,u[maxn],v[maxn],w[maxn],check;//val[]记录铁路美景
map<pair<int,int>,int> mp;//用来定位铁路的位次
struct node{
int to,next;
}e[maxn*2];
void add_edge(int u,int v){
tot++,e[tot].to=v,e[tot].next=head[u],head[u]=tot;
}
int max(int a,int b){
return a>b?a:b;
}
void dfs(int x,int w,int now){//从节点x开始遍历树。设置铁路美景值
int v,b;
vis[x]=now;
if(x==d){
flag=1;
return;
}
for(b=head[x];b;b=e[b].next){
v=e[b].to;
if(!flag&&vis[v]!=now){
dfs(v,w,now);
if(flag){
int l,r,pos;
if(x<v)l=x,r=v;
else l=v,r=x;
pos=mp[pair<int,int>(l,r)];
val[pos]=max(val[pos],w);
}
}
}
}
void judge(int x,int w,int now){//排查设置值 是否与 询问值 一致
int v,b;
vis[x]=now;
if(x==d){
flag=1;
return;
}
for(b=head[x];b;b=e[b].next){
v=e[b].to;
if(!flag&&vis[v]!=now){
judge(v,w,now);
if(flag){
int l,r,pos;
if(x<v)l=x,r=v;
else l=v,r=x;
pos=mp[pair<int,int>(l,r)];
if(val[pos]==w)check=1;
}
}
}
}
int main(){
int i,a,b,l,r;
scanf("%d",&n);
for(i=1;i<=n-1;i++){
scanf("%d%d",&a,&b);
add_edge(a,b),add_edge(b,a);
if(a<b)l=a,r=b;//l<r
else l=b,r=a;
mp[pair<int,int>(l,r)]=i;
}
scanf("%d",&m);
for(i=1;i<=m;i++){//设置值
scanf("%d%d%d",&u[i],&v[i],&w[i]);
flag=0,d=v[i],dfs(u[i],w[i],i);
}
for(i=1;i<=m;i++){//检验
flag=0,check=0,d=v[i],judge(u[i],w[i],i+m);
if(check==0)break;
}
if(check==0)printf("-1\n");
else{
for(i=1;i<=n-1;i++)
if(val[i]==0)val[i]=1;//至少得是1. 1<=fi<=10^6
printf("%d",val[1]);
for(i=2;i<=n-1;i++)printf(" %d",val[i]);
printf("\n");
}
return 0;
}