# 图论之次小题型

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define maxn 10000
using namespace std;
struct Edge{
int dist,to;
Edge(int dist,int to):dist(dist),to(to){}
bool operator < (Edge rhs) const {
return dist>rhs.dist;
}
};
int n,m;
struct Dijsktra{
int dis[maxn],dis2[maxn];
vector<Edge> G[maxn];
int n,m;
int first,second;
void init(int n,int m){
this->n=n;
this->m=m;
for (int i=0;i<n;i++)G[i].clear();
}
G[u].push_back(Edge(w,v));
G[v].push_back(Edge(w,u));
}
void dijsktra(int s){
memset(dis2,0x7f,sizeof(dis2));
memset(dis,0x7f,sizeof(dis));
dis[0]=0;
priority_queue<Edge> Q;
Q.push(Edge(0,0));
while (!Q.empty()){
Edge now=Q.top();Q.pop();
int u=now.to,d=now.dist;
if (dis2[u]<d)continue;
for (int i=0;i<G[u].size();i++){
Edge e=G[u][i];
int d2=d+e.dist;
if (dis[e.to]>d2){
swap(dis[e.to],d2);
Q.push(Edge(dis[e.to],e.to));
}
if (dis2[e.to]>d2 && dis[e.to]<d2){
dis2[e.to]=d2;
Q.push(Edge(dis2[e.to],e.to));
}
}
}
first=dis[n-1];second=dis2[n-1];
}
}map;
int main(){
scanf("%d%d",&n,&m);
map.init(n,m);
for (int i=0;i<m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);u--;v--;
}
map.dijsktra(0);
printf("%d\n%d",map.first,map.second);
return 0;
}

1.prim，然后删边增边。效率几经O（n^3)

2.从每个节点i遍历整个最小生成树，定义
F[j]为从i到j的路径上最大边的权值。遍历图求出F[j]的值，然后对于添加每条不在最小生成树中的边(i,j)，新的生成树权值之和就是MinST + w(i,j) - F[j]，记录其最小值，则为次小生成树.可以加入各种数据结构优化，比较麻烦，如果竞赛考到，一般不会太严格，此思路实现比较简单，效率O（n^2+m)。

var
vis:array[0..11000]of boolean;
dis,pre:array[0..11000]of longint;
f,g,use:array[0..1100,0..1100]of longint;
INF,n,m,max:longint;
function best(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
procedure openfile;
begin
assign(input,'second_mst.in');reset(input);
assign(output,'second_mst.out');rewrite(output);
end;
procedure closfile;
begin
close(input);close(output);
end;
function prim:longint;
var
i,tmp,pos,j:longint;
begin
fillchar(dis,sizeof(dis),$7f shr 2); fillchar(pre,sizeof(pre),$ff);
fillchar(vis,sizeof(vis),0);
dis[1]:=0;INF:=dis[0]+1;max:=0;
for i:=1 to n do
begin
tmp:=INF;
for j:=1 to n do
if (not vis[j])and(dis[j]<tmp) then
begin
tmp:=dis[j];
pos:=j;
end;
if pre[pos]<>-1 then
begin
use[pre[pos],pos]:=2;
use[pos,pre[pos]]:=2;
for j:=1 to n do
if vis[j] then
f[j,pos]:=best(f[j,pre[pos]],g[pre[pos],pos]);
end;
vis[pos]:=true;
max:=max+dis[pos];
writeln(pos,' ',dis[pos]);
for j:=1 to n do
if (not vis[j])and(g[pos,j]>0)and(g[pos,j]<dis[j]) then
begin
dis[j]:=g[pos,j];
pre[j]:=pos;
end;
end;
exit(max);
end;
function second_mst:longint;
var
sec,i,j:longint;
begin
sec:=INF;
for i:=1 to n do
for j:=1 to n do
if use[i,j]=1 then
if max+g[i,j]-f[i,j]<sec then
sec:=max+g[i,j]-f[i,j];
exit(sec);
end;
procedure init;
var
i,u,v,w:longint;
begin
for i:=1 to m do
begin
g[u,v]:=w;g[v,u]:=w;
use[u,v]:=1;use[v,u]:=1;
end;
end;
procedure main;
begin
//openfile;
init;
writeln(prim);
write(second_mst);
closfile;
end;
begin
main;
end.

#### 图论及其应用论文

2012年02月27日 1.86MB 下载

10-09 1408

11-06 608

09-06 1036

#### 图论小软件

2007年12月25日 169KB 下载

10-04 677

04-04 1169

12-04 510

05-31 354