NOIp2013提高组 货车运输
2019-09-23 22:54
106 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41996523/article/details/101231879
文章目录
题目链接
解题思路
一开始我觉得这题很难,然后觉得越做越简单。。。
我们要求每个货车的最大载重,就是要使货车走过的边权中的最小值尽可能大。我们发现,货车一定会走每个联通块内的最大生成树。
于是我先Kruskal一遍最大生成树,得到了一片森林。
我们考虑如何处理询问:
- 我们如果发现询问的两个点不在同一个联通块内(可根据Kruskal中的并查集判断),那么显然,输出-1。
- 如果在一个联通块内,我们可以使用倍增的算法来求出路径中的最小权值(有点像LCA)
详细代码
#define USEFASTERREAD 1 #define rg register #define inl inline #define DEBUG printf("qwq\n") #define DEBUGd(x) printf("var %s is %lld", #x, ll(x)) #define DEBUGf(x) printf("var %s is %llf", #x, double(x)) #define putln putchar('\n') #define putsp putchar(' ') #define Rep(a, s, t) for(rg int a = s; a <= t; a++) #define Repdown(a, t, s) for(rg int a = t; a >= s; a--) typedef long long ll; typedef unsigned long long ull; #include<cstdio> #if USEFASTERREAD char In[1 << 20], *ss = In, *tt = In; #define getchar() (ss == tt && (tt = (ss = In) + fread(In, 1, 1 << 20, stdin), ss == tt) ? EOF : *ss++) #endif namespace IO { inl void RS() {freopen("test.in", "r", stdin), freopen("test.out", "w", stdout);} inl ll read() { ll x = 0, f = 1; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + int(ch - '0'); return x * f; } inl void write(ll x) { if(x < 0) {putchar('-'); x = -x;} if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } inl void writeln(ll x) {write(x), putln;} inl void writesp(ll x) {write(x), putsp;} } using namespace IO; template<typename T> inline T Max(const T& x, const T& y) {return y < x ? x : y;} template<typename T> inline T Min(const T& x, const T& y) {return y < x ? y : x;} template<typename T> inline void Swap(T& x, T& y) {T tmp = x; x = y; y = tmp;} template<typename T> inline T Abs(const T& x) {return x < 0 ? -x : x;} #include<algorithm> #include<cstring> const int MAXN = 1e4 + 5; const int MAXM = 5e4 + 5; const int INF = 0x3f3f3f3f; int n, m; namespace Part2 {//跑lca struct Edge { int v, nxt, w; }e[MAXM << 1]; int cnt, head[MAXN]; void addedge(int u, int v, int w) { e[++cnt].w = w; e[cnt].v = v; e[cnt].nxt = head[u]; head[u] = cnt; } } namespace Part1 {//最大生成树 struct Edge { int u, v, w; bool operator < (const Edge& x)const { return w > x.w; } }e[MAXM]; int cnt; void addedge(int u, int v, int w) { e[++cnt].u = u; e[cnt].v = v; e[cnt].w = w; } int fa[MAXN]; int getfa(int x) {return x == fa[x] ? x : fa[x] = getfa(fa[x]);} void Kruskal() { for(rg int i = 1; i <= n; i++) fa[i] = i; std::sort(e + 1, e + 1 + cnt); for(rg int i = 1; i <= cnt; i++) { int fu = getfa(e[i].u), fv = getfa(e[i].v); if(fu == fv) continue; Part2::addedge(e[i].u, e[i].v, e[i].w); Part2::addedge(e[i].v, e[i].u, e[i].w); fa[fu] = fv; } } } namespace Part2 { int dep[MAXN], fa[MAXN][21], dis[MAXN][21], vist[MAXN], lg[MAXN]; void dfs(int u, int f, int w) { if(vist[u]) return; vist[u] = true; dep[u] = dep[f] + 1; dis[u][0] = w; fa[u][0] = f; for(rg int i = 1; (1 << i) <= dep[u]; i++) { fa[u][i] = fa[fa[u][i - 1]][i - 1]; dis[u][i] = Min(dis[u][i - 1], dis[fa[u][i - 1]][i - 1]); } for(rg int i = head[u]; i; i = e[i].nxt) { if(e[i].v != f) dfs(e[i].v, u, e[i].w); } } void init() { memset(dis, 0x3f, sizeof dis); lg[0] = -1; for(rg int i = 1; i <= n; i++) lg[i] = lg[i >> 1] + 1; for(rg int i = 1; i <= n; i++) if(!vist[i]) dfs(i, 0, INF); } using Part1::getfa; int LCA(int a, int b) { if(getfa(a) != getfa(b)) return -1; int ans = INF; if(dep[a] < dep[b]) Swap(a, b); while(dep[a] > dep[b]) { int stp = lg[dep[a] - dep[b]]; ans = Min(ans, dis[a][stp]); a = fa[a][stp]; } if(a == b) return ans; for(rg int i = lg[dep[a]]; i >= 0; i--) if(fa[a][i] != fa[b][i]) { ans = Min(ans, Min(dis[a][i], dis[b][i])); a = fa[a][i]; b = fa[b][i]; } ans = Min(ans, Min(dis[a][0], dis[b][0])); return ans; } } int main() { //RS(); n = read(); m = read(); for(rg int i = 1; i <= m; i++) { int u = read(), v = read(), w = read(); Part1::addedge(u, v, w); } Part1::Kruskal(); Part2::init(); int q = read(); while(q--) { int x = read(), y = read(); writeln(Part2::LCA(x, y)); } return 0; }
相关文章推荐
- Codevs 3287 NOIP2013提高组 货车运输(重庆一中高2018级信息学竞赛测验2) 解题报告
- NOIP 2013 提高组 货车运输
- 【NOIP2013提高组T3】货车运输-最大生成树+倍增LCA
- 【NOIP】提高组2013 货车运输
- NOIP提高组 2013货车运输
- NOIP提高组 2013货车运输
- NOIP2013提高组 货车运输
- [NOIP2013] 提高组 洛谷P1967 货车运输
- 洛谷P1967 [NOIP2013提高组Day1T2]货车运输
- Code[vs]3287【NOIP2013提高组】【7.13考试第四题】货车运输
- Noip 提高组 2013 Day1 T3 货车运输 Kruskal+倍增
- 题解 【luogu P1967 NOIp提高组2013 货车运输】
- NOIP2013提高组 货车运输
- JZOJsenior3534、luoguP1967.【NOIP2013提高组day1】货车运输
- NOIP提高组2013-货车运输
- NOIP2013复赛提高组day1(A:转圈游戏 B:火柴排队 C:货车运输)
- 【NOIP2013提高组 day1】货车运输
- 【noip2013提高组day1T3】 货车运输 RMQ+LCA+倍增+最大生成树
- 【BZOJ3732】Network,NOIP2013货车运输,ygylca
- 【NOIP2013】货车运输