2238: Mst
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 319 Solved: 98
[ Submit][ Status][ Discuss]
Description
给出一个
N
个点
M
条边的无向带权图,以及
Q
个询问,每次询问在图中删掉一条边后图的最小生成树。
(
各询问间独立,每次询问不对之后的询问产生影响,即被删掉的边在下一条询问中依然存在
)
Input
第一行两个正整数N,M(N<=50000,M<=100000)表示原图的顶点数和边数。
下面M行,每行三个整数X,Y,W描述了图的一条边(X,Y),其边权为W(W<=10000)。保证两点之间至多只有一条边。
接着一行一个正整数Q,表示询问数。(1<=Q<=100000)
下面Q行,每行一个询问,询问中包含一个正整数T,表示把编号为T的边删掉(边从1到M按输入顺序编号)。
Output
Q
行,对于每个询问输出对应最小生成树的边权和的值,如果图不连通则输出
“Not connected”
Sample Input
4 4
1 2 3
1 3 5
2 3 9
2 4 1
4
1
2
3
4
1 2 3
1 3 5
2 3 9
2 4 1
4
1
2
3
4
Sample Output
15
13
9
Not connected
样例解释:
无
数据规模:
10%的数据N,M,Q<=100。
另外30%的数据,N<=1000
100%的数据如题目。
13
9
Not connected
样例解释:
无
数据规模:
10%的数据N,M,Q<=100。
另外30%的数据,N<=1000
100%的数据如题目。
HINT
更新数据---2015.6.9
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 5E4 + 50;
const int maxm = maxn * 2;
const int T = 16;
const int INF = ~0U>>1;
struct E{
int x,y,w; E(){}
E(int x,int y,int w): x(x),y(y),w(w){}
bool operator < (const E &B) const {return w < B.w;}
}edgs[maxm];
int n,m,tot,q,tp,cnt,L[maxn],mfa[maxn][T],Ans[maxn],son[maxm],bfa[maxn]
,A[maxm],ch[maxn][2],stk[maxn],fa[maxn],pfa[maxn],Mark[maxn],rev[maxn];
bool bo[maxm];
vector <pair<int,int> > v[maxn];
void pushdown(int x)
{
if (rev[x])
{
swap(ch[x][0],ch[x][1]);
for (int i = 0; i < 2; i++)
if (ch[x][i]) rev[ch[x][i]] ^= 1;
rev[x] ^= 1;
}
if (Mark[x] != INF)
{
Ans[x] = min(Ans[x],Mark[x]);
for (int i = 0; i < 2; i++)
if (ch[x][i]) Mark[ch[x][i]] = min(Mark[ch[x][i]],Mark[x]);
Mark[x] = INF;
}
}
void rotate(int x)
{
int y = fa[x],z = fa[y];
pfa[x] = pfa[y]; pfa[y] = 0;
int d = ch[y][0] == x ? 0 : 1;
ch[y][d] = ch[x][d^1]; ch[x][d^1] = y;
fa[ch[y][d]] = y; fa[y] = x; fa[x] = z;
if (z) ch[z][ch[z][1] == y] = x;
}
void splay(int x)
{
for (int z = x; z; z = fa[z]) stk[++tp] = z;
while (tp) pushdown(stk[tp--]);
for (int y = fa[x]; y; rotate(x),y = fa[x])
if (fa[y]) rotate((ch[y][0] == x) ^ (ch[fa[y]][0] == y) ? x : y);
}
void Access(int x)
{
for (int u = 0; x; u = x,x = pfa[x])
{
splay(x); if (ch[x][1]) pfa[ch[x][1]] = x,fa[ch[x][1]] = 0;
ch[x][1] = u; if (u) pfa[u] = 0,fa[u] = x;
}
}
int getfa(int k) {return k == bfa[k] ? k : bfa[k] = getfa(bfa[k]);}
bool cmp(const int &x,const int &y) {return edgs[x].w < edgs[y].w;}
void ChangeRoot(int x) {Access(x); splay(x); rev[x] ^= 1;}
void Add(int x,int y) {ChangeRoot(x); pfa[x] = y; Access(x); splay(x);}
void Dfs(int x,int from)
{
Ans[x] = Mark[x] = INF;
for (int i = 1; i < T; i++) mfa[x][i] = mfa[mfa[x][i-1]][i-1];
for (int i = 0; i < v[x].size(); i++)
{
int to = v[x][i].first,id = v[x][i].second;
if (to == from) continue;
mfa[to][0] = x; L[to] = L[x] + 1;
son[id] = to; Add(x,to); Dfs(to,x);
}
}
int LCA(int p,int q)
{
if (L[p] < L[q]) swap(p,q);
for (int i = T - 1; i >= 0; i--)
if (L[p] - (1 << i) >= L[q])
p = mfa[p][i];
if (p == q) return p;
for (int i = T - 1; i >= 0; i--)
if (mfa[p][i] != mfa[q][i])
p = mfa[p][i],q = mfa[q][i];
return mfa[p][0];
}
void pushall(int x)
{
pushdown(x);
for (int i = 0; i < 2; i++)
if (ch[x][i]) pushall(ch[x][i]);
}
int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret * 10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); m = getint();
for (int i = 1; i <= m; i++)
{
int x = getint(),y,w;
y = getint(); w = getint();
edgs[i] = E(x,y,w); A[i] = i;
}
sort(A + 1,A + m + 1,cmp);
for (int i = 1; i <= n; i++) bfa[i] = i;
for (int i = 1; i <= m; i++)
{
E e = edgs[A[i]];
int fx = getfa(e.x),fy = getfa(e.y);
if (fx == fy) continue; ++cnt;
bfa[fx] = fy; tot += e.w; bo[A[i]] = 1;
v[e.x].push_back(make_pair(e.y,A[i]));
v[e.y].push_back(make_pair(e.x,A[i]));
}
if (cnt < n - 1)
{
q = getint();
while (q--) puts("Not connected");
return 0;
}
L[1] = 1; Dfs(1,0);
for (int i = 1; i <= m; i++)
{
if (bo[i]) continue;
E e = edgs[i]; int lca = LCA(e.x,e.y);
if (lca == e.x)
{
ChangeRoot(e.y); Access(e.x); splay(e.x);
Mark[ch[e.x][0]] = min(Mark[ch[e.x][0]],e.w);
}
else if (lca == e.y)
{
ChangeRoot(e.x); Access(e.y); splay(e.y);
Mark[ch[e.y][0]] = min(Mark[ch[e.y][0]],e.w);
}
else
{
ChangeRoot(e.x); Access(lca); splay(lca);
Mark[ch[lca][0]] = min(Mark[ch[lca][0]],e.w);
ChangeRoot(e.y); Access(lca); splay(lca);
Mark[ch[lca][0]] = min(Mark[ch[lca][0]],e.w);
}
}
for (int i = 1; i <= n; i++) if (!fa[i]) pushall(i);
q = getint();
while (q--)
{
int k = getint();
if (!bo[k]) printf("%d\n",tot);
else
{
int x = son[k];
if (Ans[x] == INF) puts("Not connected");
else printf("%d\n",tot - edgs[k].w + Ans[x]);
}
}
return 0;
}