目前网上好像大多数的算法都是prim,在prim的同时把d[i][j]数组给求出来
但是这个空间是O(n^2)的,如果我出题轻松可以卡掉
但是有另外一种方法。。
先求出它的最小生成树
然后一次试着加入不在最小生成树里的边
用LCA求出两边连接的节点的树上路径的权值最大的那条边的权值
比较weight[i]和那个最大权值
就好了对伐
时间复杂度O(Elogn)//常数相当小
空间复杂度O(nlogn)
这样的话就不容易被卡了对吧~
嗯那接下来
The Unique MST
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 20866 | Accepted: 7353 |
Description
Given a connected undirected graph, tell if its minimum spanning tree is unique.
Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
Input
The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.
Output
For each input, if the MST is unique, print the total cost of it, or otherwise print the string 'Not Unique!'.
Sample Input
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
Sample Output
3 Not Unique!嗯就是让你求他有没有多个最小生成树
那么就求他的次小生成树,看它是不是和最小生成树一样大么
对伐~
Code:
const shuru='1679.in';
shuchu='1679.out';
maxn=7;
type edge=record
from,too,weight:longint;
end;
fuck=record
from,too,weight,sign:longint;
end;
var f,d:array[0..101,0..maxn] of longint;
a:array[0..10000] of edge;
heap:Array[0..10000] of fuck;
ppp,pppp,p,num,x,y,z,i,j,k,n,m,ans,ans1:longint;
b:array[0..10000] of boolean;
deep,father,headlist:array[0..101] of longint;
t,next,w:array[0..10001] of longint;
mi:array[0..7] of longint;
step,now:fuck;
Function max(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
Function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(B);
end;
procedure SetIO;
begin
assign(input,shuru);
assign(output,shuchu);
reset(input);
rewrite(output);
mi[0]:=1;
for i:=1 to maxn do mi[i]:=mi[i-1]*2;
end;
procedure insert(x:longint);
var fa:longint;
begin
if x=1 then exit;
fa:=x shr 1;
if heap[x].weight<heap[fa].weight then begin
step:=heap[x];
heap[x]:=heap[fa];
heap[fa]:=step;
insert(fa);
end;
end;
procedure shit(x:longint);
var son1,son2:longint;
begin
son1:=x shl 1; son2:=x shl 1+1;
if son1>num then exit;
if son1=num then begin
if heap[x].weight>heap[son1].weight then begin
step:=heap[x];
heap[x]:=heap[son1];
heap[son1]:=step;
end;
exit;
end;
if heap[son1].weight<heap[son2].weight then begin
if heap[x].weight>heap[son1].weight then begin
step:=heap[x];
heap[x]:=heap[son1];
heap[son1]:=step;
shit(son1);
end;
end
else begin
if heap[x].weight>heap[son2].weight then begin
step:=heap[x];
heap[x]:=heap[son2];
heap[son2]:=step;
shit(son2);
end;
end;
end;
procedure memset;
begin
for i:=1 to n do begin father[i]:=i; headlist[i]:=-1; end;
fillchar(F,sizeof(f),0);
fillchar(d,sizeof(D),0);
fillchar(b,sizeof(b),false);
p:=0;
ans:=0;
end;
procedure addedge(a,b,c:longint);
begin
inc(num);
heap[num].from:=a;
heap[num].too:=b;
heap[num].weight:=c;
heap[num].sign:=num;
insert(num);
end;
procedure init;
begin
num:=0;
readln(n,m);
for i:=1 to m do
begin
with a[i] do readln(from,too,weight);
addedge(a[i].from,a[i].too,a[i].weight);
end;
memset;
end;
function find(n:longint):longint;
var x,pp:longint;
begin
pp:=n;
while pp<>father[pp] do pp:=father[pp];
while n<>pp do
begin
x:=father[n];
father[n]:=pp;
n:=x;
end;
exit(pp);
end;
procedure merge(a,b:longint);
var fa1,fa2:longint;
begin
fa1:=find(a); fa2:=find(b);
father[fa2]:=fa1;
end;
Function ask(x,y:longint):longint;
var del,i:longint;
begin
if deep[x]>deep[y] then begin
pppp:=x;
x:=y;
y:=pppp;
end;
del:=deep[y]-deep[x];
ask:=0;
for i:=0 to maxn do if (del and mi[i])<>0 then begin
ask:=max(ask,d[y,i]);
y:=f[y,i];
end;
if x<>Y then begin
for i:=maxn downto 0 do
if f[x,i]<>f[y,i] then begin
ask:=max(ask,d[x,i]);
ask:=max(ask,d[y,i]);
x:=f[x,i];
y:=f[y,i];
end;
ask:=max(ask,d[x,0]);
ask:=max(ask,d[y,0]);
end;
exit(ask);
end;
procedure DFS(u,father:longint);
var i:longint;
begin
for i:=1 to maxn do f[u,i]:=f[f[u,i-1],i-1];
for i:=1 to maxn do d[u,i]:=max(d[u,i-1],d[f[u,i-1],i-1]);
i:=headlist[u];
while i<>-1 do
begin
if t[i]=father then begin
i:=next[i];
continue;
end;
f[t[i],0]:=u;
d[t[i],0]:=w[i];
deep[t[i]]:=deep[u]+1;
DFS(t[i],u);
i:=next[i];
end;
end;
procedure main;
begin
init;
for i:=1 to n-1 do
begin
now:=heap[1];
heap[1]:=heap[num];
dec(num);
shit(1);
while find(now.from)=find(now.too) do
begin
now:=heap[1];
heap[1]:=heap[num];
dec(num);
shit(1);
end;
x:=find(now.from); y:=find(now.too);
merge(x,y);
x:=now.from; y:=now.too; z:=now.weight; b[now.sign]:=true;
inc(p);
next[p]:=headlist[x];
headlist[x]:=p;
w[p]:=z;
t[p]:=y;
inc(p);
next[p]:=headlist[y];
headlist[y]:=p;
w[p]:=z;
t[p]:=x;
inc(ans,z);
end;
deep[1]:=1;
DFS(1,0);
ans1:=maxlongint;
for i:=1 to m do
begin
if b[i] then continue;
k:=ask(a[i].from,a[i].too);
if a[i].weight=k then begin
writeln('Not Unique!');
exit;
end;
end;
writeln(ans);
end;
begin
SetIO;
readln(ppp);
while ppp>0 do
begin
main;
dec(ppp);
end;
close(input);
close(output);
end.