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,x1,y1,x2,y2, w, representing there is a road with cost w connecting the cities on (x1,y1)(x1,y1) and (x2,y2).(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
∙1≤T≤50.∙1≤T≤50.
∙1≤m≤4000.∙1≤m≤4000.
∙−10000≤xi,yi≤10000.∙−10000≤xi,yi≤10000.
∙1≤w≤105.∙1≤w≤105.
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
题意:题目就是要找一个最小环 ,可枚举每一条边(最小环至少由3个点构成,枚举每一条边,计算该边从起点到终点且不经过该直达边的最短路,再加上该条直达边,这就构成了一个环,之后取最小值即可)(该方法暴力些,其他博客有更好的做法,但我觉得该方法较容易理解)
#include<iostream>
#include<cstring>
#include<map>
#include<queue>
#include<stdio.h>
using namespace std;
typedef pair<int,int>P;
map<P,int>mp; //用map来存点(P是一个坐标,int是一个点的编号)
const int INF=0x3f3f3f3f;
const int maxn=4010;
int head[maxn<<1],dis[maxn<<1],vis[maxn<<1]; //总共4000条边,但是最多不过8000个点
int cnt,tol,minn;
struct Edge
{
int v,w,next;
}e[maxn<<1];
struct node
{
int u,v,w;
}a[maxn]; //用来存取每一条边
void Init() //初始化
{
mp.clear();
cnt=1;
tol=1;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w) //前向星
{
e[cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt++;
}
void Dijkstra(int s,int t,int ww) //从s到t的最短路(不经过s->t这条直达边)
{
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[s]=0;
priority_queue<P,vector<P>,greater<P> >que;
que.push(P(0,s)); //0为最短距离,s为定点编号
while(!que.empty())
{
P p=que.top();
que.pop();
if(p.first+ww>minn) //如果该点的最短距离加上s->t这条直达边的权值
break; //大于了记录答案的minn,就不算。
int u=p.second;
if(vis[u])
continue;
vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
int w=e[i].w;
if((u==s&&v==t)||(u==t&&v==s)) //不经过s->t这条直达边(双向边).(其实不加后面的也能过)
continue;
if(!vis[v]&&dis[v]>dis[u]+w) //更新
{
dis[v]=dis[u]+w;
que.push(P(dis[v],v));
}
}
}
}
int main()
{
int t,k=1,m;
cin>>t;
while(t--)
{
Init();
cin>>m;
for(int i=1;i<=m;i++)
{
int x1,y1,x2,y2,w;
cin>>x1>>y1>>x2>>y2>>w;
if(!mp[P(x1,y1)])
mp[P(x1,y1)]=tol++; //用tol从1开始为每一个新出现的点编号
if(!mp[P(x2,y2)])
mp[P(x2,y2)]=tol++;
int u=mp[P(x1,y1)]; //转换成编号之间的关系
int v=mp[P(x2,y2)];
add(u,v,w);
add(v,u,w);
a[i].u=u,a[i].v=v,a[i].w=w;//存边枚举
}
minn=INF;
for(int i=1;i<=m;i++) //枚举
{
Dijkstra(a[i].u,a[i].v,a[i].w);
minn=min(minn,dis[a[i].v]+a[i].w);
}
printf("Case #%d: %d\n",k++,minn==INF?0:minn);
}
return 0;
}