zoukankan      html  css  js  c++  java
  • loj#2718. 「NOI2018」归程

    题目链接

    loj#2718. 「NOI2018」归程

    题解

    按照高度做克鲁斯卡尔重构树
    那么对于询问倍增找到当前点能到达的高度最小可行点,该点的子树就是能到达的联通快,维护子树中到1节点的最短距离
    spfa她死了...同步赛没写的说...
    似乎前两题比去年简单些....连蒟蒻我都可做前两题的说

    代码

    #include<queue> 
    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' || c > '9')c = getchar(); 
    	while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
    	return x * f; 
    } 
    #define mp std::make_pair
    #define pr std::pair<int,int> 
    int n,m; 
    const int maxn = 1000007; 	
    struct node { 
    	int u,v,a,l,next; 
    	bool operator  < (const node & A)const { 
    		return a > A.a; 
    	} 
    } edge[maxn << 1],e[maxn]; 
    
    
    int num = 0,head[maxn],dis[maxn << 1]; 
    inline void add_edge(int u,int v,int w) { edge[++ num].v = v;edge[num].l = w;edge[num].next = head[u];head[u] = num;  }  
    std::priority_queue<pr> q; 
    void dijkstar() { 
    	static bool vis[maxn]; 
    	memset(dis,0x3f,sizeof dis); memset(vis,0,sizeof vis); 
    	dis[1] = 0;q.push(pr(0,1)); 
    	while(!q.empty()) { 
    		int u = q.top().second;q.pop(); 
    		if(vis[u]) continue; 
    		vis[u] = 1; 
    		for(int i = head[u];i;i = edge[i].next) { 
    			int v = edge[i].v; 
    			if(dis[v] > dis[u] + edge[i].l) dis[v] = dis[u] + edge[i].l,q.push(mp(-dis[v],v)); 
    		} 
    	} 
    } 
    int fa[maxn]; 
    int find(int x) { if(fa[x] != x) fa[x] = find(fa[x]); return fa[x];  } 
    int tot = 0,dad[maxn << 1][20],mn[maxn << 1]; 
    int lastans = 0; 
    int query(int x,int p) {  
    	for(int i = 18;i >= 0;-- i) { 
    		if(mn[dad[x][i]] > p) x = dad[x][i]; 
    	} 
    	return dis[x]; 
    }  
    void solve() { 
    	int Q = read(),k = read(),S = read(),v,p; 
    	if(k) while(Q --) { 
    		v = (read() + k * lastans - 1) % n + 1; 
    		p = (read() + k * lastans ) % (S + 1); 
    		printf("%d
    ",lastans = query(v,p)); 
    		
    	} else while(Q --) { 
    		v = read(),p = read(); 
    		printf("%d
    ",query(v,p)); 
    	} 
    } 
    void init() { 
    	n = read(),m = read(); 
    	//int cnt = 0; 
    	for(int u,v,a,l,i = 1;i <= m;++ i) { 
    		u = read(),v = read(),l = read(),a = read(); 
    		e[i].u = u,e[i].v = v,e[i].a = a; 
    		add_edge(u,v,l); add_edge(v,u,l); 
    	} 
    	dijkstar(); 
    	for(int i = 1;i <= n;++ i) fa[i] = i; 
    	tot = n; 
    	std::sort(e + 1,e + m + 1); 
    	int k = 1; 
    	for(int fx,fy,i = 1;i <= m;++ i) { 
    		int x = e[i].u,y = e[i].v,h = e[i].a; 
    		if((fx = find(x)) == (fy = find(y))) continue; 
    		fa[fx] = fa[fy] = dad[fx][0] = dad[fy][0] = ++ tot; fa[tot] = dad[tot][0] = tot; 
    		mn[tot] = e[i].a; dis[tot] = std::min(dis[fx],dis[fy]); 
    		if(++ k == n)break;  
    	} 
    	/*for(int i = 1;i <= tot;++ i) 
    		for(int j = 0;dad[i][j];++ j) 
    			dad[i][j + 1] = dad[dad[i][j]][j],mn[i][j + 1] = std::min(mn[i][j],mn[dad[i][j]][j]);  
    	*/ 
    	for(int i = 1;i <= 18;++ i) 
    		for(int x = 1;x <= tot;++ x)dad[x][i] =  dad[dad[x][i - 1]][i - 1]; 
    	solve(); 
    } 
    int main() { 
    	freopen("return.in","r",stdin); freopen("return.out","w",stdout);
    	int t = read(); 
    	while(t --) { 
    		memset(head,0,sizeof head),num = 0; lastans = 0; 
    		init(); 	
    	} 
    	return 0; 
    } 
    
  • 相关阅读:
    IIS 和 各个协议
    Hibernate 框架基本知识
    各类主流框架及设计模式简介
    PHP微信公众开发笔记(七)
    PHP微信公众开发笔记(六)
    《Programming in Lua 3》读书笔记(二十七)
    《Programming in Lua 3》读书笔记(二十八)
    《Programming in Lua 3》读书笔记(二十六)
    PHP微信公众开发笔记(五)
    PHP微信公众开发笔记(四)
  • 原文地址:https://www.cnblogs.com/sssy/p/9351267.html
Copyright © 2011-2022 走看看