• [做题记录-乱做] Luogu3783 [SDOI2017]天才黑客


    边转点,然后前缀优化。
    清空的时候要清空倍增数组!

    /*
    	QiuQiu /qq
      ____    _           _                 __                
      / __   (_)         | |               / /                
     | |  | |  _   _   _  | |  _   _       / /    __ _    __ _ 
     | |  | | | | | | | | | | | | | |     / /    / _` |  / _` |
     | |__| | | | | |_| | | | | |_| |    / /    | (_| | | (_| |
      \___\_ |_|  \__,_| |_|  \__, |   /_/      \__, |  \__, |
                                __/ |               | |     | |
                               |___/                |_|     |_|
    */
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    class Input {
    	#define MX 1000000
    	private :
    		char buf[MX], *p1 = buf, *p2 = buf;
    		inline char gc() {
    			if(p1 == p2) p2 = (p1 = buf) + fread(buf, 1, MX, stdin);
    			return p1 == p2 ? EOF : *(p1 ++);
    		}
    	public :
    		Input() {
    			#ifdef Open_File
    				freopen("a.in", "r", stdin);
    				freopen("a.out", "w", stdout);
    			#endif
    		}
    		template <typename T>
    		inline Input& operator >>(T &x) {
    			x = 0; int f = 1; char a = gc();
    			for(; ! isdigit(a); a = gc()) if(a == '-') f = -1;
    			for(; isdigit(a); a = gc()) 
    				x = x * 10 + a - '0';
    			x *= f;
    			return *this;
    		}
    		inline Input& operator >>(char &ch) {
    			while(1) {
    				ch = gc();
    				if(ch != '
    ' && ch != ' ') return *this;
    			}
    		}
    		inline Input& operator >>(char *s) {
    			int p = 0;
    			while(1) {
    				s[p] = gc();
    				if(s[p] == '
    ' || s[p] == ' ' || s[p] == EOF) break;
    				p ++; 
    			}
    			s[p] = '';
    			return *this;
    		}
    	#undef MX
    } Fin;
    
    class Output {
    	#define MX 1000000
    	private :
    		char ouf[MX], *p1 = ouf, *p2 = ouf;
    		char Of[105], *o1 = Of, *o2 = Of;
    		void flush() { fwrite(ouf, 1, p2 - p1, stdout); p2 = p1; }
    		inline void pc(char ch) {
    			* (p2 ++) = ch;
    			if(p2 == p1 + MX) flush();
    		}
    	public :
    		template <typename T> 
    		inline Output& operator << (T n) {
    			if(n < 0) pc('-'), n = -n;
    			if(n == 0) pc('0');
    			while(n) *(o1 ++) = (n % 10) ^ 48, n /= 10;
    			while(o1 != o2) pc(* (--o1));
    			return *this; 
    		}
    		inline Output & operator << (char ch) {
    			pc(ch); return *this; 
    		}
    		inline Output & operator <<(const char *ch) {
    			const char *p = ch;
    			while( *p != '' ) pc(* p ++);
    			return * this;
    		}
    		~Output() { flush(); } 
    	#undef MX
    } Fout;
    
    #define cin Fin
    #define cout Fout
    #define endl '
    '
    
    using LL = long long;
    
    const int N = 2e6 + 10;
    
    int loc[N], whi[N];
    
    namespace Trie {
    	int n;
    	vector<int> e[N];
    	void push(int x, int y) { e[x].push_back(y); e[y].push_back(x); }
    	int lg[N];
    	int fa[N][20], dep[N], dfn[N];
    	void dfs(int x, int fx) {
    	//	cerr << x << endl;
    		fa[x][0] = fx; dep[x] = dep[fx] + 1; dfn[x] = ++ dfn[0];
    		for(int i = 1; i <= lg[dep[x]]; i ++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
    		for(int y : e[x]) if(y != fx) dfs(y, x);
    	}
    	int lca(int x, int y) {
    		if(dep[x] < dep[y]) swap(x, y);
    		while(dep[x] > dep[y]) x = fa[x][lg[dep[x] - dep[y]]];
    		if(x == y) return x;
    		for(int i = lg[dep[x]]; i >= 0; i --) if(fa[x][i] ^ fa[y][i]) x = fa[x][i], y = fa[y][i];
    		return fa[x][0];
    	}
    	int dep_lca(int x, int y) { return dep[lca(x, y)] - 1; }
    	void build() {
    		dfn[0] = 0;
    		memset(fa, 0, sizeof(fa));
    		for(int i = 2; i <= n; i ++) lg[i] = lg[i >> 1] + 1;
    		dfs(1, 0);
    	}
    	inline bool cmp(int x, int y) { return dfn[whi[x]] < dfn[whi[y]]; }
    }
    
    using Trie :: dep_lca;
    using Trie :: cmp;
    
    int n, m;
    
    // 点 边 trie
    vector<int> node[N];
    int trie[N];
    struct edge {
    	int to, next, w;
    } e[N << 2];
    int cnt, head[N];
    
    void push(int x, int y, int w) {
    	//cerr << x << ' ' << y << ' ' << w << endl;
    	e[++ cnt] = (edge) {y, head[x], w}; head[x] = cnt;
    }
    int tot, S;
    
    void clr() {
    	cnt = 0;
    	for(int i = 1; i <= tot; i ++) head[i] = 0;
    	for(int i = 1; i <= n; i ++) node[i].clear();
    	for(int i = 1; i <= Trie :: n; i ++) Trie :: e[i].clear();
    	memset(loc, 0, sizeof(loc));
    	tot = 0; S = 0;
    }
    
    
    
    void linkit(int id) {
    	static int pre_out[N], pre_in[N], suf_out[N], suf_in[N], lk[N];
    	vector<int> &v = node[id]; //cerr << v.size() << endl;
    	//cerr << v[0] << endl;
    	sort(v.begin(), v.end(), cmp);
    	int sz = v.size();
    	for(int i = 1; i <= sz; i ++) pre_in[i] = ++ tot;
    	for(int i = 1; i <= sz; i ++) pre_out[i] = ++ tot;
    	for(int i = 1; i <= sz; i ++) suf_in[i] = ++ tot;
    	for(int i = 1; i <= sz; i ++) suf_out[i] = ++ tot;
    	for(int i = 2; i <= sz; i ++) push(pre_out[i - 1], pre_out[i], 0), push(pre_in[i], pre_in[i - 1], 0);
    	for(int i = sz - 1; i >= 1; i --) push(suf_in[i], suf_in[i + 1], 0), push(suf_out[i + 1], suf_out[i], 0);
    	for(int i = 0; i < sz - 1; i ++) lk[i + 1] = dep_lca(whi[v[i]], whi[v[i + 1]]);
    	//for(int i = 1; i <= sz; i ++) {
    	//	cerr << v[i - 1] << ' ';
    	//} cerr << endl;
    	for(int i = 1; i <= sz; i ++) {
    		int x = v[i - 1]; //cerr << x << endl;
    		//cerr << x << ' ' << pre_out[i] << endl;
    		if(x > m) push(x, pre_out[i], 0), push(x, suf_out[i], 0);
    		else push(pre_in[i], x, 0), push(suf_in[i], x, 0);
    	} 
    	for(int i = 1; i <= sz - 1; i ++) {
    		push(pre_out[i], suf_in[i + 1], lk[i]);
    		push(suf_out[i + 1], pre_in[i], lk[i]);
    	}
    }
    
    using ll = long long;
    
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    
    ll dis[N];
    int vis[N];
    void dijskra() {
    	memset(dis, 0x3f, sizeof(dis));
    	memset(vis, 0, sizeof(vis));
    	dis[S] = 0;
    	priority_queue<pair<int, int> > q;
    	q.push({0, S});
    	while(q.size()) {
    		int x = q.top().second; q.pop();
    		if(vis[x]) continue;
    		vis[x] = 1;
    //		cerr << x << endl;
    		for(int i = head[x]; i; i = e[i].next) {
    			int y = e[i].to, w = e[i].w;
    		//	cerr << x << ' ' << y << ' ' << w << endl;
    			if(dis[y] > dis[x] + w) {
    				dis[y] = dis[x] + w;
    				q.push({- dis[y], y});
    			}
    		}
    	}
    	//cerr << dis[1] << endl;
    }
    
    ll ans[N];
    
    void solve() {
    	cin >> n >> m >> Trie :: n;
    	tot = m * 2; S = ++ tot;
    	for(int i = 1; i <= m; i ++) {
    		int a, b, c, d;
    		cin >> a >> b >> c >> d;
    		node[b].push_back(i + m);
    		node[a].push_back(i);
    		trie[i] = trie[i + m] = d;
    		loc[i + m] = b;
    		whi[i] = whi[i + m] = d;
    		push(i, i + m, c);
    		if(a == 1) {
    			push(S, i, 0);
    		//	cerr << S << ' ' << i << endl;
    		}
    	}
    	for(int i = 1; i <= Trie :: n - 1; i ++) {
    		int x, y, w;
    		cin >> x >> y >> w;
    		Trie :: push(x, y);
    	//	Trie :: push(y, x);
    	}
    	Trie :: build();//cerr << "ok" << endl;
    //	cout << dep_lca(4, 5) << endl;
    	for(int i = 1; i <= n; i ++) linkit(i);
    //	linkit(2); 
    //	linkit(4);
    	dijskra();
    	for(int i = 1; i <= n; i ++) ans[i] = INF;
    //	for(int i = 1; i <= m * 2; i ++) cerr << loc[i] << endl;
    //	cerr << dis[6] << endl;
    	for(int i = 1; i <= m * 2; i ++) ans[loc[i]] = min(ans[loc[i]], dis[i]);
    	
    	for(int i = 2; i <= n; i ++) cout << ans[i] << endl;
    	clr();
    }
    
    int main() {
    	//freopen("a.in", "r", stdin);
    	int Case; cin >> Case;
    	while(Case --) solve();
    	return 0;
    }
    
  • 相关阅读:
    hdu 1686 Oulipo
    [NOI1997] 积木游戏
    错误录——未完待续
    NOI 2014 魔法森林
    hdu 4010 Query on The Trees
    求助大佬6——1种贪心
    51 nod 1205 流水线调度
    bzoj 1180: [CROATIAN2009]OTOCI
    HNOI2010 弹飞绵羊
    SDOI2008 洞穴勘测
  • 原文地址:https://www.cnblogs.com/clover4/p/15322571.html
Copyright © 2020-2023  润新知