传送门:www.lydsy.com:808/JudgeOnline/problem.php?id=3669
考场上弱……写了40分……考完加了两行优化……就TM70了!卧槽……
40/70分算法:
枚举a,排序b,从小到大跑生成树,注意不能二分,a不满足二分性质
优化:只枚举a出现过的值,就可以70……唉……弱……
100分算法:
把边按a从小到大排序
然后一条条加边
动态维护b的最小生成树
假设现在加入的边是(x,y) a b
那么答案=min(答案,a+树上1到n路径上的b的最大值)
用LCT维护
40分Code:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=50010;
const int maxm=1e5+10;
int n,m,mid,ans=INT_MAX;
int getint(){
int x;scanf("%d",&x);return x;
}
void putint(int x){
printf("%d\n",x);
}
struct edge{
int u,v,a,b;
edge(int _u=0,int _v=0,int _a=0,int _b=0):
u(_u),v(_v),a(_a),b(_b){}
bool operator<(const edge &x)const{
return b<x.b;
}
};
int fa[maxn];
void init(){for(int i=1;i<=n;i++)fa[i]=i;}
int find(int x){if(fa[x]!=x)return fa[x]=find(fa[x]);return x;}
void Union(int a,int b){fa[find(a)]=find(b);}
edge edges[maxm];
bool ok(){
init();
int maxB=0;
for(int i=1;i<=m;i++){
int u=edges[i].u,v=edges[i].v,a=edges[i].a,b=edges[i].b;
if(a>mid)continue;
int f1=find(u),f2=find(v);
if(f1==f2)continue;
Union(f1,f2);
maxB=max(maxB,b);
if(find(1)==find(n))break;
}
if(find(1)!=find(n))return false;
else{
ans=min(ans,mid+maxB);
return true;
}
}
int main(){
int maxa=0;
n=getint();m=getint();
init();
for(int i=1;i<=m;i++){
edges[i].u=getint();
edges[i].v=getint();
edges[i].a=getint();
edges[i].b=getint();
if(edges[i].u==edges[i].v){
edges[i].a=INT_MAX;
continue;
}
maxa=max(maxa,edges[i].a);
Union(edges[i].u,edges[i].v);
}if(find(1)!=find(n)){
puts("-1");return 0;
}sort(edges+1,edges+1+m);
for(mid=0;mid<=maxa;mid++)
ok();
cout<<ans<<endl;
return 0;
}
抄了wangxz神犇的LCT模板好久终于A了……
AC Code:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=50010;
const int maxm=1e5+10;
int n,m,mid,ans=INT_MAX;
int getint(){
char ch=0;int res=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))(res*=10)+=ch-'0',ch=getchar();
return res;
}
void putint(int x){
printf("%d\n",x);
}
struct edge{
int u,v,a,b;
edge(int _u=0,int _v=0,int _a=0,int _b=0):
u(_u),v(_v),a(_a),b(_b){}
bool operator<(const edge &x)const{
return a<x.a;
}
};
int fa[maxn];
int find(int x){if(fa[x]!=x)return fa[x]=find(fa[x]);return x;}
void Union(int a,int b){fa[find(a)]=find(b);}
edge edges[maxm];
struct node{
int rev,val;
node *c[2],*p,*maxx;
node(){
rev=val=0;
maxx=this;
}
void pushdown(){
if(rev){
c[0]->rev^=1;
c[1]->rev^=1;
swap(c[0],c[1]);
rev^=1;
}
}
node* rz(){
maxx=this;
if(c[0]->maxx->val>maxx->val)maxx=c[0]->maxx;
if(c[1]->maxx->val>maxx->val)maxx=c[1]->maxx;
return this;
}
void sets(node *x,int d){
pushdown();
(c[d]=x)->p=this;
rz();
}
bool d(){
return p->c[1]==this;
}
bool root(){
return p->c[0]!=this&&p->c[1]!=this;
}
}pool[maxn+maxm];
void newnode(node *x,int i){
static int tot=0;
x=pool+(++tot);
x->rev=0;x->val=edges[i].b;x->maxx=x;
x->c[0]=x->c[1]=x->p=pool;
}
void rot(node *x){
node *y=x->p;
if(!y->root())y->p->pushdown();
y->pushdown();
x->pushdown();
int d=x->d();
y->sets(x->c[!d],d);
if(y->root())x->p=y->p;
else y->p->sets(x,y->d());
x->sets(y,!d);
}
void splay(node *x){
for(;!x->root();rot(x))
if(x->p->root());
else if(x->d()==x->p->d())rot(x->p);
else rot(x);
}
node *access(node *x){
node *y=pool;
for(;x!=pool;x=x->p){
splay(x);
x->sets(y,1);
y=x;
}return y;
}
void makert(node *x){
access(x)->rev^=1;
splay(x);
}
node *qmax(node *u,node *v){
makert(u);
access(v);
splay(v);
return v->maxx;
}
node *findrt(node *x){
for(x=access(x);x->pushdown(),x->c[0]!=pool;x=x->c[0]);
return x;
}
void link(node *x,node *y){
makert(x);
x->p=y;
access(x);
}
void cut(node *y){
splay(y);
y->c[0]->p=y->p;
y->c[1]->p=pool;
y->c[0]=y->c[1]=y->p=pool;
y->maxx=y;
y->val=0;
}
void add(node *u,node *v,node *w){
if(findrt(u)==findrt(v)){
node *x=qmax(u,v);
if(x->val<w->val)return;
cut(x);
v->rz();
link(v,w);
link(w,u);
}else{
link(v,w);
link(w,u);
}
}
#define id(i) (pool+i)
int main(){
n=getint();m=getint();
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
edges[i].u=getint();
edges[i].v=getint();
edges[i].a=getint();
edges[i].b=getint();
Union(edges[i].u,edges[i].v);
}if(find(1)!=find(n)){
puts("-1");return 0;
}sort(edges+1,edges+1+m);
for(int i=0;i<=n+m;i++)
id(i)->p=id(i)->c[0]=id(i)->c[1]=pool,id(i)->maxx=id(i);
int ans=INT_MAX;
for(int i=1;i<=m;i++){
id(i+n)->val=edges[i].b;
node *u=edges[i].u+pool,*v=edges[i].v+pool,*w=i+n+pool;
add(u,v,w);
if(findrt(id(1))==findrt(id(n)))
ans=min(ans,edges[i].a+qmax(id(1),id(n))->val);
}cout<<ans<<endl;
return 0;
}