2055. Urban GeographyTime limit:2.0 Second
Memory limit:128 MB
Android Vasya prepares a project in Urban geography. The aim of the project is to improve the infrasructure of the city he lives in. Now the city consists of n districts, some of which is connected by roads. Using These roads one can get from any district to any other district of the city by car. Vasya thinks that such big amount of roads makes citizens use their own cars instead of walking or cycling. He wants to close as many roads for cars as possible and turn them into boulevards. Of course, Vasya wants to keep the possibility to get from any district to any other district of the city by car using Roa Ds. Now citizens pay for using roads, and prices for different roads may vary very much. Vasya thinks that leaving open some expensive and some cheap roads at the same time isn't a good idea beacuse it can incr Ease social tension in the city. That's why he wants-minimize the price spread between the most expensive and the cheapest roads. Help Vasya choose the roads toKeep open. InputThe first line contains integers nиm is the number of the city districts and roads correspondingly (2≤n≤50 000; N−1≤m≤50 000). The next m lines contain triples of integers a I, b i and c I, meaning that between the city districts a I and b i t Here are a road with the price c I (1≤a I, b i≤n; a i≠b i; 1≤c i≤10 9). There can several roads between, districts.OutputThe only line output the sequence of integers-numbers of the roads which should is kept open in the city. The roads is numbered as they appear in the input data. If There is several solutions, output any of them.Samples
input |
Output |
3 3
1 2 1
2 3 3
3 1 4
|
2 3
|
4 5
1 2 1
2 3 1
1 3 2
1 4 2
2 4 1
|
1 2 5
|
problem Author:Nikita Burlakov
problem Source:Ural Sport Programming Championship 2015
Build a tree, which is the longest edge-the shortest edge is the smallest.
Maintain MST with a dynamic tree. Updates the minimum distance.
Build a dynamic tree:
Establish a node for each point. Create a node for each edge. Add Edge <u,v> if u,v on the same tree
Put u,v,access into the same splay, find the smallest node x,cut (x,v), Cut (X,u)
Turn the u,v into the root of your own tree, and then create a point X,link (x,u) for the side, Link (x,v).
The dynamic tree maintains the weights of the edges in the tree.
44case T has been a day. There is no way, a different way to do it, next time come back to do this problem
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <set
> Using namespace std;
#define MAXN 400007 #define INF 1000000000 int cnt = 0;
struct node{Node *fa,*ch[2];
BOOL Root,rev;
int val,mval;
Node () {} node* init (int v,node *f) {fa = f;
Ch[0] = ch[1] = f;
root = true;
val = Mval = v;
Rev = false;
return this;
} void Update () {mval = val;
if (Ch[0]->mval < mval) Mval = ch[0]->mval;
if (Ch[1]->mval < mval) Mval = ch[1]->mval;
} void Update_rev () {if (val = = inf + 10000000) return;
Rev =!rev;
Swap (ch[0],ch[1]);
} void Pushdown () {if (rev.) {Ch[0]->update_rev ();
Ch[1]->update_rev ();
Rev = false;
}} void Rotate () {Node *f = fa, *ff = f->fa;
int t = (f->ch[1] = = this); if (f->root) root = True, F->root = false;
else ff->ch[ff->ch[1] = = f] = this;
FA = FF;
F->CH[T] = ch[t^1];
CH[T^1]->FA = f;
Ch[t^1] = f;
F->FA = this;
F->update ();
} void push () {if (!root) Fa->push ();
Pushdown ();
} void Splay () {push ();
Node *f, *ff;
while (!root) {f = Fa,ff = f->fa;
if (!f->root) if ((ff->ch[1]==f) && (f->ch[1] = = this)) f->rotate ();
else rotate ();
Rotate ();
} update ();
}
};
Node POOL[MAXN];
Node *NIL,*TREE[MAXN];
void init () {cnt = 1;
Nil = tree[0] = pool;
Nil->val = nil---mval = inf+10000000;
}//Take x to the root of the path and form a path****** node *access (node *x) {node *y = nil;
while (x! = nil) {x->splay ();
X->ch[1]->root = true;
(x->ch[1] = y)->root = false; X->update ();
y = x;
x = x->fa;
} return y;
}//Turn node x into root ****** void be_root (node *x) {//cout<<x->val-inf<<endl;
Access (x);
X->splay ();
X->update_rev ();
Update_rev (x);
}//Connect X to node F on ****** void link (node *x, node *f) {be_root (x);
X->FA = f;
}//separates x, y ****** void cut (Node *x,node *y) {be_root (x);
Access (x);
Y->splay ();
Y->fa = nil;
} node *findminnode (node *x) {if (x->val <= x->ch[0]->mval && x->val <= x->ch[1]->mval)
return x;
if (X->ch[0]->mval < X->ch[1]->mval) return Findminnode (X->ch[0]);
Return Findminnode (x->ch[1]);
} node *findroot (node *x) {if (x->ch[0] = = nil) return x;
Return FindRoot (x->ch[0]);
} struct edge{int u,v,w;
Edge () {} int getn () {int n = 0;
char x;
while (1) {x = GetChar (); if (x = = ' | | x = = ' \ n ') return n;
n = n*10+x-' 0 ';
}} void Init () {u = GETN ();
v = getn ();
W = GETN ();
}
};
Edge EDGE[MAXN];
int fa[100007];
int find (int u) {if (fa[u] = = u) return u;
return Fa[u] = find (Fa[u]);
} multiset<int>haha;
int comp1 (int a,int b) {return EDGE[A].W < EDGE[B].W;}
int id[100007];
int main () {//freopen ("j.in", "R", stdin);
Freopen ("Jl.out", "w", stdout);
int n,m;
while (scanf ("%d%d", &n,&m)!=eof) {haha.clear ();
Edge.clear ();
Edge e;
GetChar ();
for (int i = 0;i < m; i++) {edge[i].init ();
if (edge[i].u = = edge[i].v) {m--;
i--;
Continue
} Id[i] = i;
} sort (ID,ID+M,COMP1);
Init ();
for (int i = 1;i <= n;i++) tree[i] = Pool[cnt++].init (Inf+i,nil);
int num = N,ans=1000000000,be,en;
Node *x,*y,*z; FoR (int i = 0;i < m; i++) {int u = edge[id[i]].u,v = EDGE[ID[I]].V,W=EDGE[ID[I]].W;
Haha.insert (w);
z = pool[cnt++].init (w,nil);
Be_root (Tree[u]);
x = Access (Tree[v]);
y = findRoot (x);
if (tree[u] = = y) {x = Findminnode (x);
Cut (X,tree[u]);
Cut (X,tree[v]);
Haha.erase (Haha.find (x->val));
num++;
} link (tree[u],z);
Link (tree[v],z);
num--;
if (num = = 1) {int mval = *haha.begin ();
if (W-mval < ans) {ans = w-mval;
be = Mval;
En = w;
}}} num = n;
for (int i = 0;i <= n; i++) fa[i] = i;
for (int i = 0;i < m; i++) {e = edge[i];
if (e.w >= be && e.w <= en) { int f1 = find (E.U);
int F2 = find (E.V);
if (f1! = F2) {FA[F1] = Fa[f2];
if (num! = N) putchar (");
printf ("%d", i+1);
num--;
}}} printf ("\ n");
} return 0;
}