对着答案调了三天,还是TLE#13,求助
查看原帖
对着答案调了三天,还是TLE#13,求助
1088320
Mr_Nobody_楼主2023/11/19 14:18

树上倍增和kruskal,一直卡在第十三个测试点超时无果,调了三天也不知道哪里出问题了,求大佬帮帮

#include <bits/stdc++.h>
using namespace std;
const long int N = 100005;
const long int M = 4e+5;

inline unsigned int maxx(unsigned int a,unsigned int b){return (a < b) ? b : a;}

inline unsigned int read() {
    unsigned int x=0;
	char ch=getchar();
	while(ch<'0' || ch>'9')
	{
		ch=getchar();
	}
	while(ch>='0' && ch<='9')
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x;
}
unsigned int n,m;
struct KruskalTreeEdges{
    unsigned int a,b,w;
    char used;
    inline bool operator<(const KruskalTreeEdges& i2){
        return w < i2.w;
    }
}KruskalEdge[300005];
struct Star
{
    unsigned int to,weight,next;
}StarMap[200005];
unsigned int head[N],cnt = 0;                    //head[u]的u是节点的数字名称
unsigned int fa[N],maxl[N][20],depth[N],secl[N][20],g[N][20];          //前向星序列集合fa->Kruskal,maxl最大,secl次大

unsigned long long int MinimumTree,FinalAns = 92233720368547758;
inline unsigned int find(unsigned int node){
    return (node == fa[node]) ? node : find(fa[node]);
}

inline void addEdge(unsigned int u,unsigned int v,unsigned int w){        //加边函数
    StarMap[++cnt].to = v;
    StarMap[cnt].weight = w;
    StarMap[cnt].next = head[u];        //初始边是0
    head[u] = cnt;
}

inline void dfs(unsigned int node,unsigned int fa1){
    unsigned int to;
    for(unsigned int i = head[node];i;i = StarMap[i].next){
        to = StarMap[i].to;
        if(to != fa1){
            g[to][0] = node;
            maxl[to][0] = StarMap[i].weight;
            depth[to] = depth[node] + 1;
            dfs(to,node);
        }
    }
}

inline unsigned int LCA(unsigned int u,unsigned int v){
    if(depth[u] < depth[v]){swap(u,v);}//确保u深
    for(register short int j = 18;j >= 0;--j){
        if(depth[g[u][j]] >= depth[v]){u = g[u][j];}
    }

    if(u == v){//若同一个点,则返回
        return u;
    }

    for(register short int j = 18;j >= 0;--j){
        if(g[u][j] != g[v][j]){
            u = g[u][j];
            v = g[v][j];
        }
    }
    return g[u][0];
}

inline unsigned int get_ans(unsigned int u,unsigned int v,unsigned int w){     //这个函数返回环里面的严格次长边
    unsigned int lca = LCA(u,v),left = 0,right = 0;
    for(register short int j = 18;j >= 0;--j){
        if(depth[g[u][j]] >= depth[lca]){
            if(maxl[u][j] != w){
                left = maxx(maxl[u][j],left);
            } else {
                left = maxx(secl[u][j],left);
            }
            u = g[u][j];
        }
    }

    for(register short int j = 18;j >= 0;--j){
        if(depth[g[v][j]] >= depth[lca]){
            if(maxl[v][j] != w){
                right = maxx(maxl[v][j],right);
            } else {
                right = maxx(secl[v][j],right);
            }
            v = g[v][j];
        }
    }
    return maxx(left,right);
}

int main(){
    unsigned int u,v,w,pointer = 0;
    n = read();m = read();
    for(register unsigned int i = 1;i <= m;++i){
        u = read();v = read();w = read();
        if (u != v) KruskalEdge[++pointer] = {u,v,w};
    }
    m = pointer;

    sort(KruskalEdge+1,KruskalEdge+m+1);
    unsigned int currentEdges = 0;
    for(unsigned int i = 1;i <= n;++i){fa[i] = i;head[i] = 0;}
    unsigned int af,bf;
    for(register unsigned int i = 1;i <= m;++i){
        af = find(KruskalEdge[i].a);bf = find(KruskalEdge[i].b);
        if(af != bf){
            fa[af] = bf,MinimumTree += KruskalEdge[i].w,KruskalEdge[i].used = 1;
            addEdge(KruskalEdge[i].a,KruskalEdge[i].b,KruskalEdge[i].w);
            addEdge(KruskalEdge[i].b,KruskalEdge[i].a,KruskalEdge[i].w);    //前向星加边
            if(++currentEdges == n-1){break;}
        }
    }
    // for(int i = 0;i <= N;i++) depth[i] = 1;
    //LCA回溯开始
    dfs(1,0);
    for(register unsigned short int i=1;i<=18;++i)
	{
		for(register unsigned int j=1;j<=n;++j)
		{
			g[j][i]=g[g[j][i-1]][i-1],maxl[j][i]=maxx(maxl[j][i-1],maxl[g[j][i-1]][i-1]),secl[j][i]=maxx(secl[j][i-1],secl[g[j][i-1]][i-1]);
			if(maxl[j][i-1]<maxl[g[j][i-1]][i-1] && secl[j][i]<maxl[j][i-1])
			{
				secl[j][i]=maxl[j][i-1];
			}
			else if(maxl[j][i-1]>maxl[g[j][i-1]][i-1] && secl[j][i]<maxl[g[j][i-1]][i-1])
			{
				secl[j][i]=maxl[g[j][i-1]][i-1];
			}
		}
	}

    unsigned int temp;
    for(register unsigned int i = 1;i <= m;++i){
        if(KruskalEdge[i].used == 0){
            temp = get_ans(KruskalEdge[i].a,KruskalEdge[i].b,KruskalEdge[i].w);
            if(FinalAns > MinimumTree - temp + KruskalEdge[i].w){
                FinalAns = MinimumTree - temp + KruskalEdge[i].w;
            }
        }
    }
    printf("%llu",FinalAns);
    return 0;
}
2023/11/19 14:18
加载中...