关闭

图论之次小题型

96人阅读 评论(0) 收藏 举报
分类:

次短路:设最短路d[i],次短路d2[i],我们可以很明确次d2[i]=d[j]+(i,j)或d2[i]=d2[j]+(i,j)。dijsktra最短路的同时替换次短路即可。

参考程序:

#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();
	}
	void addedge(int u,int v,int w){
		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.addedge(u,v,w);
	}
	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)。

这里给出去年打的pascal程序,C的日后再补上。

参考程序(prim):

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
  readln(n,m);
  for i:=1 to m do
   begin
     readln(u,v,w);
     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.


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:30475次
    • 积分:2012
    • 等级:
    • 排名:第19980名
    • 原创:170篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条