Hdu 6005 Pandaland 无向图最小环:最短路剪枝

Pandaland

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 897    Accepted Submission(s): 210


Problem Description
Mr. Panda lives in Pandaland. There are many cities in Pandaland. Each city can be treated as a point on a 2D plane. Different cities are located in different locations.
There are also M bidirectional roads connecting those cities. There is no intersection between two distinct roads except their endpoints. Besides, each road has a cost w.
One day, Mr. Panda wants to find a simple cycle with minmal cost in the Pandaland. To clarify, a simple cycle is a path which starts and ends on the same city and visits each road at most once.
The cost of a cycle is the sum of the costs of all the roads it contains.
 

Input
The first line of the input gives the number of test cases, T. T test cases follow.
Each test case begins with an integer M.
Following M lines discribes roads in Pandaland.
Each line has 5 integers  x1,y1,x2,y2,  w, representing there is a road with cost w connecting the cities on  (x1,y1)  and  (x2,y2).
 

Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the cost Mr. Panda wants to know.
If there is no cycles in the map, y is 0.

limits


1T50.
1m4000.
10000xi,yi10000.
1w105.
 

Sample Input
  
  
2 5 0 0 0 1 2 0 0 1 0 2 0 1 1 1 2 1 0 1 1 2 1 0 0 1 5 9 1 1 3 1 1 1 1 1 3 2 3 1 3 3 2 1 3 3 3 1 1 1 2 2 2 2 2 3 3 3 3 1 2 2 1 2 2 1 3 2 4 1 5 1 4
 

Sample Output
  
  
Case #1: 8 Case #2: 4
 

Source


二维平面很多点和边,让你找无向图最小环。


求最小环,只要枚举每条边,把它去掉,求边两头的最短路。

这题数据较多,不妨加一个小剪枝:当迪杰斯特拉的优先队列顶的距离大于当前答案时,直接跳出。

然后就过了。就过了。。。。


补充:poj 3895 求无向图,边权都为1的最长环

做法:先随便dfs出一棵生成树,dfs的时候,记录每个点在树里的深度,每到一个点扫描所有边,顺便更新答案就可以。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=8005,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
const ld pi=acos(-1.0L);
int head[maxn],dist[maxn];
bool visit[maxn];
int num,ans;
map<pair<int,int>,int> mp; 

struct Edge {
	int from,to,dist,pre;
};
Edge edge[maxn*2];

void addedge(int f,int t,int d) {
	edge[num].from=f;edge[num].to=t;edge[num].dist=d;
	edge[num].pre=head[f];head[f]=num++;
	edge[num].from=t;edge[num].to=f;edge[num].dist=d;
	edge[num].pre=head[t];head[t]=num++;
}

struct node {
	int id,dist;
	node(int id,int dist):id(id),dist(dist) {}
	bool operator <(const node &x)const {
	    return dist>x.dist;
	}
};

int dj(int n,int s,int t) {
	int j,i;
	mem0(visit);
	priority_queue<node> pq;
	visit[s]=1;
	for (j=head[s];j!=-1;j=edge[j].pre) 
		pq.push(node(j,edge[j].dist));
	meminf(dist);dist[s]=0;
	for (int k=1;k<n;k++) {
		if (pq.top().dist>ans) break;
		i=pq.top().id;
		int to=edge[i].to;
		if (visit[to]) continue;
		visit[to]=1;
		dist[to]=pq.top().dist;
		pq.pop();
		for (j=head[to];j!=-1;j=edge[j].pre) 
			if (!visit[edge[j].to]&&dist[to]+edge[j].dist<ans) 
				pq.push(node(j,dist[to]+edge[j].dist));
	}
	return dist[t];
}

int main() {
	int cas,cnt=0;
	scanf("%d",&cas);
	while (cas--) {
		cnt++;
		int n,i,j,x,y,s,t,d,m=0;
		mp.clear();
		num=0;memset(head,-1,sizeof(head));
		scanf("%d",&n);
		ans=inf;
		for (i=1;i<=n;i++) {
			scanf("%d%d",&x,&y);
			s=mp[make_pair(x,y)];
			if (!s) s=mp[make_pair(x,y)]=++m;
			scanf("%d%d%d",&x,&y,&d);
			t=mp[make_pair(x,y)];
			if (!t) t=mp[make_pair(x,y)]=++m;
			addedge(s,t,d);
		}
		for (i=0;i<n;i++) {
			d=edge[i*2].dist;
			edge[i*2].dist=edge[i*2+1].dist=inf;
			int x=dj(m,edge[i*2].from,edge[i*2].to);
			ans=min(ans,x+d);
			edge[i*2].dist=edge[i*2+1].dist=d;
		}
		if (ans==inf) ans=0;
		printf("Case #%d: %d\n",cnt,ans);
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值