HDU---6005:Pandaland(无向图最小环)

题意:

给定一个无向图,求一个边权和最小的环

分析:

求最小环可以O(n^3)的Floyd,也可以枚举删边,假设当前删除边(u,v),那么删除后u到v的最短距离dis[u][v] + w[u][v]便是这个环的最小花费,枚举删边+堆优化的dijkrtra,时间复杂度(m*m*logn),这题要剪枝,(1)所求最短路的终点已经出队列,return(2)队列中的最小值大于答案,return(此题这个才是能过的剪枝)

代码:

#include <bits/stdc++.h>

#define pii pair<int,int>

using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1e4+15;
const int maxm = 8e3+43;
int t,cnt,m,x,y,w,u,v,p,res,head[maxm];
struct edge{
	int to,nxt,w;
}e[maxm<<1];
struct cmp{
	bool operator()(const pii a,const pii b){
		return a.second > b.second;
	}
};
map<pii,int> vis;
inline void add(int x,int y,int _w){
	e[++cnt].to = y;e[cnt].w = _w;
	e[cnt].nxt = head[x];head[x] = cnt;
}
int dis[maxm];
void init(){
	vis.clear();
	cnt = 0;res = inf;p = 0;
	memset(head,0,sizeof(head));
}
void dijkstra(int x,int y){
	memset(dis,inf,sizeof(dis));
	priority_queue<pii,vector<pii>,cmp> q;
	dis[x] = 0;
	q.push(pii(x,0));
	while(!q.empty()){
		pii now = q.top();q.pop();
		int uu = now.first;         
		if(uu == y || now.second > res) return ;            //剪枝
		if(dis[uu] < now.second) continue;
		for(int i = head[uu];i;i = e[i].nxt){
			int vv = e[i].to;
			if((uu==x&&vv==y)||(uu==y&&vv==x)) continue;  //这条边是删除的边
			if(dis[vv] > dis[uu]+e[i].w){
				dis[vv] = dis[uu] + e[i].w;
				q.push(pii(vv,dis[vv]));
			}
		}
	}
}
int main(){
	scanf("%d",&t);
	for(int Case = 1; Case <= t; ++Case){
		init();
		scanf("%d",&m);
		for(int i = 1;i <= m; ++i){
			scanf("%d %d",&x,&y);
			if(!vis[pii(x,y)]) u = ++p,vis[pii(x,y)] = u;
			else u = vis[pii(x,y)];
			scanf("%d %d %d",&x,&y,&w);
			if(!vis[pii(x,y)]) v = ++p,vis[pii(x,y)] = v;
			else v = vis[pii(x,y)];
			add(u,v,w);
			add(v,u,w);
		}
		for(int i = 1;i <= p; ++i){
			for(int j = head[i]; j ;j = e[j].nxt){
				if(i >= e[j].to) continue;
				dijkstra(i,e[j].to);
				res = min(res,dis[e[j].to]+e[j].w);
			}
		}
		printf("Case #%d: %d\n",Case,res==inf ? 0:res);	
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_41157137/article/details/89476899
今日推荐