15分 AC#1,11,17
查看原帖
15分 AC#1,11,17
243672
する楼主2023/8/21 00:02

CF的双倍经验过了,比正确答案大

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,cnt,t,now,ans=2000000000000000000,edgesum,vis[200005],num[200005],g,s;
struct node{int fa,ls,rs,val,id,maxi,tag;}tree[200005];
struct Edge{int id,u,v,a,w;}edge[200005],edge2[200005];
map<pair<int,int>,int> mp;
bool cmp(Edge x,Edge y){return x.a<y.a;}
bool cmp2(Edge x,Edge y){return x.w>y.w;}
void pushup(int cur)
{
	if(tree[cur].val>tree[tree[cur].ls].maxi&&tree[cur].val>tree[tree[cur].rs].maxi) tree[cur].maxi=tree[cur].val,tree[cur].id=cur;
	else if(tree[tree[cur].ls].maxi>tree[tree[cur].rs].maxi) tree[cur].maxi=tree[tree[cur].ls].maxi,tree[cur].id=tree[tree[cur].ls].id;
	else tree[cur].maxi=tree[tree[cur].rs].maxi,tree[cur].id=tree[tree[cur].rs].id;
}
int get(int cur)
{
	if(tree[tree[cur].fa].ls==cur) return 0;
	if(tree[tree[cur].fa].rs==cur) return 1;
	return -1;
}
void connect(int cur,int fa,int opt)
{
	tree[cur].fa=fa;
	if(opt==0) tree[fa].ls=cur;
	if(opt==1) tree[fa].rs=cur;
}
void rotate(int x)
{
	int y=tree[x].fa;
	int z=tree[y].fa;
	int opx=get(x),opy=get(y);
	int u=0;
	if(opx==0) u=tree[x].rs;
	if(opx==1) u=tree[x].ls;
	connect(u,y,opx);
	connect(y,x,opx^1);
	connect(x,z,opy);
	pushup(x),pushup(y);
}
void pushdown(int cur)
{
	if(tree[cur].tag==0) return ;
	swap(tree[cur].ls,tree[cur].rs);
	if(tree[cur].ls!=0) tree[tree[cur].ls].tag^=1;
	if(tree[cur].rs!=0) tree[tree[cur].rs].tag^=1;
	tree[cur].tag=0;
}
void pushfa(int cur)
{
//	cout<<cur<<" "<<tree[cur].ls<<" "<<tree[cur].rs<<"\n";
	if(get(cur)!=-1) pushfa(tree[cur].fa);
	pushdown(cur);
}
void splay(int cur)
{
	if(cur==0) return ;
	pushfa(cur);
	while(get(cur)!=-1)
	{
//		cout<<"*";
		int fa=tree[cur].fa;
		if(get(fa)==-1) rotate(cur);
		else if(get(cur)==get(fa)) rotate(fa),rotate(cur);
		else rotate(cur),rotate(cur);
	}
}
void access(int cur)
{
	int son=0;
	while(cur!=0)
	{
//		cout<<"*";
		splay(cur);
		tree[cur].rs=son;
		pushup(cur);
		son=cur;
		cur=tree[cur].fa;
	}
}
void makeroot(int cur)
{
	access(cur);
	splay(cur);
	swap(tree[cur].ls,tree[cur].rs);
	if(tree[cur].ls!=0) tree[tree[cur].ls].tag^=1;
	if(tree[cur].rs!=0) tree[tree[cur].rs].tag^=1;
} 
void split(int x,int y)
{
	makeroot(x);
	access(y);
	splay(y);
}
int findroot(int cur)
{
	access(cur);
	splay(cur);
	while(tree[cur].ls!=0) pushdown(cur),cur=tree[cur].ls;
	splay(cur);
	return cur;
}
void link(int x,int y)
{
	makeroot(x);
	if(findroot(y)==x) return ;
	tree[x].fa=y;
}
void cut(int x,int y)
{
	if(findroot(x)!=findroot(y)) return ;
	split(x,y);
	if(tree[x].fa!=y||tree[x].rs!=0) return ;
	tree[x].fa=tree[y].ls=0;
	pushup(x);
}
void insert(int kth,int id,int x,int y,int w)
{
	if(x==y) return ;
	if(findroot(x)!=findroot(y))
	{
		link(x,id);link(y,id);
		vis[kth]=1;
		edgesum++;
	}
	else
	{
		split(x,y);
		if(tree[y].maxi>w)
		{
			int nid=tree[y].id;
			cut(edge[nid].u,nid);cut(edge[nid].v,nid);
			vis[num[edge[nid].id]]=0;
			link(x,id);link(y,id);
			vis[kth]=1;
		}
	}
	if(edgesum==n-1)
	{
		while(vis[now]==0) now++;
//		cout<<now<<"\n";
		ans=min(ans,edge2[now].w+edge[id].a);
	}
}
signed main()
{
	cin>>n>>m;
	now=1;
	for(int i=n+1;i<=m+n;i++){edge[i].id=i;cin>>edge[i].u>>edge[i].v>>edge[i].a>>edge[i].w;edge2[i-n]=edge[i];}
	sort(edge+n+1,edge+n+m+1,cmp);
	sort(edge2+1,edge2+m+1,cmp2);
	for(int i=1;i<=m;i++) num[edge2[i].id]=i;
	for(int i=n+1;i<=n+m;i++)
	{
		tree[i].val=tree[i].maxi=edge[i].w,tree[i].id=i;
		insert(num[edge[i].id],i,edge[i].u,edge[i].v,edge[i].w);
	}
	if(ans==2000000000000000000) ans=-1;
	cout<<ans;
	return 0;
}// 
2023/8/21 00:02
加载中...