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.
找带权最小环
因为有4000条边,所以点的个数最大8000;不能用floyd
所以暴力枚举每一条边跑Dijkstra,题目不存在重边
剪枝优化:如果在Dijkstra中出来的边已经大于当期的ans-w(ij)那么直接跳出
因为只有当d比ans-w(ij)小的时候才会更新答案
注意边的个数...和 0 (因为这挖了好久把边数当成了m)
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstring>
#include<set>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 1e15+10
using namespace std;
const int maxn=40005;
struct edge{
ll u,v,w,next;
}e[maxn];
ll g[maxn],vis1[maxn],d[maxn];
ll n,m,tot;
struct node{
ll v,w;
bool operator < (const node &cmp) const{
return w>cmp.w;
}
};
void init()
{
mem(e,0);
mem(g,0);
tot=n=0;
}
void creat_edge(ll u,ll v,ll w)
{
e[++tot]=(edge){u,v,w,g[u]};
g[u]=tot;
}
ll dj(ll st,ll ed,ll cheek)
{
priority_queue<node>q;
mem(vis1,0);
for(ll i=1;i<=n;i++)
d[i]=inf;
d[st]=0;
q.push((node){st,0});
while(!q.empty())
{
ll now=q.top().v;
if(q.top().w>cheek) break;
q.pop();
if(vis1[now]) continue;
vis1[now]=1;
for(ll i=g[now];i>0;i=e[i].next)
{
ll u=e[i].u,v=e[i].v,w=e[i].w;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
q.push((node){v,d[v]});
}
}
}
return d[ed];
}
int main()
{
ll t;
scanf("%lld",&t);
for(ll k=1;k<=t;k++)
{
map<ll,map<ll,ll> >q,vis;
init();
scanf("%lld",&m);
for(ll i=1;i<=m;i++)
{
ll x1,x2,y1,y2,w,u,v;
scanf("%lld%lld%lld%lld%lld",&x1,&y1,&x2,&y2,&w);
if(!q[x1][y1]) q[x1][y1]=++n;
if(!q[x2][y2]) q[x2][y2]=++n;
u=q[x1][y1];
v=q[x2][y2];
creat_edge(u,v,w);
creat_edge(v,u,w);
}
ll ans=inf;
for(int i=1;i<=n;i++)
for(int j=g[u];j>0;j=e[j].next)
{
ll u=e[j].u,v=e[j].v,w=e[j].w;
if((vis[u][v]<w&&vis[u][v]!=0)||(vis[v][u]<w&&vis[v][u]!=0)) continue;
vis[u][v]=vis[v][u]=1;
e[i].w=inf;
ll temp=dj(u,v,ans-w)+w;
// cout<<temp<<endl;
ans=min(ans,temp);
e[i].w=w;
}
if(ans==inf) printf("Case #%lld: 0
",k);
else printf("Case #%lld: %lld
",k,ans);
}
}