从T=空集开始
for(图中每条边e)
if 加入e不构成环,则 T=T+e
else e‘ 是环上权重最大的边,T = T+e'
解:利用邻接表形式存储图,用另一张图,每一次向新图里面加入一条边,从加入边的顶点开始做dfs遍历。如果遇到后向边,就说明图中有环,找出最大的边,删掉该边,再加入边,继续dfs过程,直到所有边都加入。
这里图用hashmap存储,
static Map<Integer, LinkedList<Pair<Integer, Integer>>> graph = new HashMap<>();//邻接表存储图 ,pair存到达点和权重
初始化:
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void ini() {
System.out.println("请输入顶点数:");
v = scanner.nextInt();
visited = new int[v];
pre = new int[v];
System.out.println("请输入边数和各条边以及权重:");
e = scanner.nextInt();
for(int i=0; i<e; i++)
{
resGraph.put(i, new LinkedList<>());
graph.put(i, new LinkedList<>());
}
for(int i=0; i<e; i++)
{
int from = scanner.nextInt();
int to = scanner.nextInt();
int weight = scanner.nextInt();
if(weight<=0) {
System.out.println("权重必须大于0!\n重新输入:");
weight = scanner.nextInt();
}
graph.get(from).add(new Pair(to, weight));
graph.get(to).add(new Pair(from, weight));//双向添加
//DFS(from, visited, graph);
}
printGrapg(graph);
}
深度优先搜索:
//dfs遍历
public static void DFS(int start, int[] visited ,Map<Integer, LinkedList<Pair<Integer, Integer>>> graph) {
for(int i=0; i<v; i++) {
visited[i] = white;//初始化都是白色
pre[i] = -1;//没有前驱点
}
dfsVisit(0, visited, graph);//从0开始遍历
}
//dfs递归部分
public static void dfsVisit(int start,int[] visited, Map<Integer,LinkedList<Pair<Integer, Integer>>> graph) {
time++;
visited[start] = gray;
for(Pair<Integer, Integer> p:graph.get(start))
{
if(visited[p.getKey()]==gray && p.getKey()!=pre[start])//是灰色出现了环,后向边
{
findMax(start, p.getKey(), p.getValue(), graph);//标记
}
if(visited[p.getKey()]==white)
{
pre[p.getKey()] = start;
dfsVisit(p.getKey(), visited, graph);
}
}
visited[start] = black;
time++;
}
找最大权重的边:这里用pre数组记录了每一个点的前向点,根据此来找到环和最大边
//找最大权值的边
public static void findMax(int end, int start, int weight, Map<Integer,LinkedList<Pair<Integer, Integer>>> graph) {
//System.out.println("bugbugbugbugbug:"+end+" "+start+" "+weight);
int a = pre[end], endP = end;
int maxKey = 0, w=0, maxEnd=start;
while(a!=pre[start]) {
w = findWeight(endP, a);
if(maxKey <= w) {
maxEnd = endP;
maxKey = w;
}
endP = a;
a = pre[endP];
}
if(maxKey>weight) {//最大的是树边里面的
//isMax.put(maxEnd, pre[maxEnd]);
delete(graph, maxEnd, pre[maxEnd]);
delete(graph, pre[maxEnd], maxEnd);
}else {
//isMax.put(end, start);//最大边是该后向边
delete(graph, end, start);
delete(graph, start, end);
}
}
主函数:
for(int i=0; i<v;i++)
{
for(int j=0; j<graph.get(i).size(); j++)
{
from = i; to = graph.get(i).get(j).getKey(); w = graph.get(i).get(j).getValue();
if(from<to)
{
resGraph.get(from).add(new Pair<Integer, Integer>(to, w));//每次添加一条边
resGraph.get(to).add(new Pair<Integer, Integer>(from, w));
DFS(to, visited, resGraph);
}
}
}
int count=0;
for(int i=0; i<v; i++) {
System.out.print("\n"+i+" :: ");
for(Pair<Integer, Integer> p : resGraph.get(i))
{
System.out.print(" "+i+"->"+p.getKey()+" "+p.getValue());//i->p 3
count+=p.getValue();
}
}
System.out.println(count/2);