/*
poj1679
次小生成树问题。
白书中讲到,对于最小生成树,可以通过添加一条边-删除一条边的方法获得
在u-v间添加一条边,会形成一条回路,需要删除最小生成树上这之间的最大的边,
所以我们需要先预处理出节点对的瓶颈路 maxc(u,v)=max(maxc(u,t),c(t,v))
从而获得候选的次小生成树
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int MAXN=105;
int cases;
struct edge{
	int s;
	int t;
	int d;
	int idx;
	bool vis;
	bool operator<(const edge &a)const{
		return d<a.d;
	}
};
struct kruscal{
	int n,m;
	vector<int>g[MAXN];
	vector<edge>e;
	int cnt;
	int fa[MAXN];
	int maxd[MAXN][MAXN];
	int dfsr[MAXN],ded;
	bool isfa[MAXN]; 
	bool visp[MAXN];//无向图有一个边对应两个方向,后边dfs时需要防重复访问
	void init(){
		cnt=ded=0;
		memset(maxd,0,sizeof(maxd));
		memset(isfa,true,sizeof(isfa));
		memset(visp,false,sizeof(visp));
		for(int i=0;i<MAXN;i++){
			g[i].clear();
			fa[i]=i;
		}
		e.clear();
	}
	void add_edge(int a,int b,int c){
		e.push_back((edge){a,b,c,e.size(),false});
		e.push_back((edge){b,a,c,e.size(),false});
		g[a].push_back(e.size()-2);
		g[b].push_back(e.size()-1);
	}
	int find_fa(int x){
		return fa[x]=(fa[x]==x?x:find_fa(fa[x]));
	} 
	void unite(int x,int y){
		int fax=find_fa(x);
		int fay=find_fa(y);
		fa[fax]=fay;
	}
	int solve(){
		int ans=0;
		vector<edge>ee(e);
		sort(ee.begin(),ee.end());
		for(int i=0;i<ee.size();i++)
			if(!e[ee[i].idx].vis){
				edge &now=e[ee[i].idx];
				if(find_fa(now.s)!=find_fa(now.t)){
					e[ee[i].idx^1].vis=now.vis=true;
					isfa[now.t]=false;
					unite(now.s,now.t);
					ans+=now.d;
					cnt++;
				}
				if(cnt==n-1)
					break;
			}
		return ans;
	}
	int dfs(int x){
		for(int i=0;i<g[x].size();i++){
			if(e[g[x][i]].vis&&!visp[e[g[x][i]].t]){
				visp[e[g[x][i]].t]=true;
				for(int j=0;j<ded;j++){
					maxd[dfsr[j]][e[g[x][i]].t]=maxd[e[g[x][i]].t][dfsr[j]]=e[g[x][i]].d;
					maxd[dfsr[j]][e[g[x][i]].t]=maxd[e[g[x][i]].t][dfsr[j]]=max(maxd[e[g[x][i]].t][dfsr[j]],maxd[x][dfsr[j]]);
				}
				dfsr[ded++]=e[g[x][i]].t;

				dfs(e[g[x][i]].t);
			}
		}
	}
	int get_sub(){
		int mst=solve();
		int root;
		for(int i=1;i<=n;i++)
			if(isfa[i]){
				root=i;
				break;
			}
		visp[root]=true;
		dfsr[ded++]=root;
		dfs(root);
		int ans=214748364;
		for(int i=0;i<e.size();i++)
			if(!e[i].vis) 
				ans=min(ans,mst+e[i].d-maxd[e[i].s][e[i].t]);
		if(ans==mst)
			printf("Not Unique!\n");
		else
			printf("%d\n",mst);
		return ans;
	}
}k;
int main(){
	// freopen("1.in","r",stdin);
	// freopen("1.out","w",stdout);
	scanf("%d",&cases);
	while(cases--){
		k.init();
		scanf("%d%d",&k.n,&k.m);
		for(int i=1;i<=k.m;i++){
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			k.add_edge(a,b,c);
		}
	k.get_sub();
	}
	return 0;
}
 posted on 2017-09-22 17:37  cylcy  阅读(79)  评论(0编辑  收藏  举报