蒟!蒻!悬!关!
  • 板块P1186 玛丽卡
  • 楼主whileAK
  • 当前回复5
  • 已保存回复5
  • 发布时间2023/10/12 16:31
  • 上次更新2023/11/2 14:18:13
查看原帖
蒟!蒻!悬!关!
817925
whileAK楼主2023/10/12 16:31

蒟蒻已经调了好几天啦QAQ

这几天我从99分的暴力,变成0分正解,又变成31,41,81,21,50……现在卡在81分再也上不去了,小数据也被我下载完过掉了

本蒟蒻不咋会图论,不喜请喷QAQ

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 
int n,m,ans,no2,pr[1005],pre[1005],f[1005],fa[1005][15],id[1001],d[1005],cnt=0;
bool b[1005];
struct ed{
	int to;
	int val;
};
struct node{
	int point;
	int val;
	int nx;
    bool operator <(const node &x)const{
        return x.val<val;
    }
};
struct shu{
	int l,r,val;
}me[1000005];
priority_queue<node>q;
vector<ed>v[1005];
vector<int>tr[1005];
inline void dij(int ss){//最短路 
	memset(f,0x3f,sizeof(f));
	memset(b,false,sizeof(b));
	f[ss]=0;
	q.push((node){ss,0});
	while(q.size()){
		node u=q.top();q.pop();
		int p=u.point,s=v[u.point].size(),g;
		if(b[p])continue;
		b[p]=true;
		for(int i(0);i<s;++i){
			g=v[p][i].to;
			if(b[g])continue;
			if(f[g]>f[p]+v[p][i].val){
				f[g]=f[p]+v[p][i].val;
				pr[g]=p;
				q.push((node){g,f[g]});
			}
		}
	}
}
void dfs(int p,int bf,int de){//最短路树 
	fa[p][0]=bf;d[p]=de;
	for(int i(1);i<=14;++i)fa[p][i]=fa[fa[p][i-1]][i-1];
	for(int i(0);i<tr[p].size();++i)dfs(tr[p][i],p,de+1);
}
int lca(int x,int y){//倍增求lca 
	if(d[x]>d[y])swap(x,y);
	int h=d[y]-d[x],g=0;
	for(;h;h>>=1){
		if(h&1)y=fa[y][g];
		++g;
	}
	if(x==y)return x;
	for(int i(14);~i;--i){
		if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
	}
	return fa[x][0];
}
bool cmp(shu x,shu y){
	return x.val>y.val;
}
struct tree{
	int ll,rr,val,tag;
}t[100005];
void build(int l,int r,int p){//建线段树 
	t[p].ll=l,t[p].rr=r,t[p].val=0x7fffffff,t[p].tag=0x7fffffff;
	if(l==r)return;
	int mid=l+r>>1;
	build(l,mid,2*p),build(mid+1,r,2*p+1);
}
void up(int p){//上传 
	t[p].val=max(t[2*p].val,t[2*p+1].val);
}
void spread(int p){//下传 
	if(t[p].tag!=0x7fffffff){
		t[2*p].tag=min(t[2*p].tag,t[p].tag);
		t[2*p+1].tag=min(t[2*p+1].tag,t[p].tag);
		t[2*p].val=min(t[2*p].val,t[p].tag);
		t[2*p+1].val=min(t[2*p+1].val,t[p].tag);
		t[p].tag=0x7fffffff;
	}
}
void assign(int l,int r,int z,int p){//区间赋值 
	if(t[p].ll>=l&&t[p].rr<=r){
		t[p].val=min(t[p].val,z);t[p].tag=min(t[p].val,z);
		return;
	}
	spread(p);
	int mid=t[p].ll+t[p].rr>>1;
	if(l<=mid)assign(l,r,z,2*p);
	if(r>mid)assign(l,r,z,2*p+1);
	up(p);
}
int main(){
	scanf("%d%d",&n,&m);
	for(register int i(1),x,y;i<=m;++i){
		scanf("%d%d%d",&x,&y,&f[1]);
		v[x].push_back((ed){y,f[1]});
		v[y].push_back((ed){x,f[1]});
	}
	dij(1);ans=f[n];
	memcpy(pre,pr,sizeof(pr));
	for(int i(1);i<=n;++i)tr[pr[i]].push_back(i);
	dfs(1,0,1);
	no2=n;
	while(no2){
		id[no2]=++cnt;no2=pre[no2];
	}
	int u,nn=cnt,x,y,xx,yy;
	cnt=0;
	for(register int i(1);i<=n;++i){
		for(register int j(0);j<v[i].size();++j){
			u=v[i][j].to;//考虑每条边的贡献 ,区间取min 
			if(pre[u]!=i&&pre[i]!=u){
				x=lca(n,u),y=lca(n,i);xx=u,yy=i;
				if(id[x]<id[y])swap(x,y),swap(xx,yy);
				if(id[x]-1>=id[y])me[++cnt].l=id[y],me[cnt].r=id[x]-1,me[cnt].val=v[i][j].val+f[yy]-f[y]+f[xx]+f[n]-f[y];
			}
		}
	}
	sort(me+1,me+cnt+1,cmp);//按赋值从大到小进行赋值操作 
	build(1,nn-1,1);
	for(int i(1);i<=cnt;++i)assign(me[i].l,me[i].r,me[i].val,1),printf("%d %d %d\n",me[i].l,me[i].r,me[i].val);//赋值 
	ans=max(ans,t[1].val);//取全局最大值 
	printf("%d",ans);
	return 0;
}
2023/10/12 16:31
加载中...