题意:
给出一个二维平面上的 \(m\) 条边和边的端点的坐标,求出图的最小环的长度。
数据范围:
\(1≤T≤50\)
\(1≤m≤4000\)
\(−10000≤x_i,y_i≤10000\)
\(1≤w≤10^5\)
解法1:(暴力+ \(dijsktra\)剪枝)
删边,跑 \(m\) 次 \(dijsktra\) ,同时注意剪枝,对于当前队列中最小的长度,如果已经比答案要大,肯定不行。
一开始觉得这样做肯定超时,但看到网上的题解很多都是这做的,于是试了试。外加快读,链式前向星来优化,跑了 \(343ms\),有点惊讶。
代码:
#include <bits/stdc++.h>
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int M=4e3+5;
map<int,map<int,int> >mp;
struct node
{
int from,to,val,next;
}edge[M<<2];
int dis[M<<1],head[M<<1];
priority_queue<P,vector<P>,greater<P> >que;
int ans,cot;
void init()
{
memset(head,-1,sizeof(head));
cot=1;
}
void addedge(int from,int to,int w)
{
edge[cot].from=from;
edge[cot].to=to;
edge[cot].val=w;
edge[cot].next=head[from];
head[from]=cot++;
}
void read(int &x)
{
x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
x*=f;
}
int dij(int s,int t,int w)
{
while(!que.empty())
que.pop();
que.push(make_pair(0,s));
dis[s]=0;
while(!que.empty())
{
P now=que.top();
que.pop();
if(now.first+w>ans)
return inf;
if(dis[now.second]<now.first)
continue;
if(now.second==t)//不加会t,加了后:343ms
return dis[t];
for(int i=head[now.second];i!=-1;i=edge[i].next)
{
node tmp=edge[i];
if(tmp.val>=inf)
continue;
if(dis[tmp.to]>now.first+tmp.val)
{
dis[tmp.to]=now.first+tmp.val;
que.push(make_pair(dis[tmp.to],tmp.to));
}
}
}
return dis[t];
}
int main()
{
int t,cnt=0,m;
read(t);
while(t--)
{
init();
read(m);
mp.clear();
int a,b,c,d,e;
int num=0;
ans=inf;
for(int i=1;i<=m;i++)
{
read(a),read(b),read(c),read(d),read(e);
if(mp[a][b]==0)
mp[a][b]=++num;
if(mp[c][d]==0)
mp[c][d]=++num;
addedge(mp[a][b],mp[c][d],e);
addedge(mp[c][d],mp[a][b],e);
}
for(int i=1;i<cot;i+=2)
{
int tv=edge[i].val;
edge[i].val=inf;
edge[i+1].val=inf;
fill(dis+1,dis+num+1,inf);
int res=dij(edge[i].from,edge[i].to,tv);
ans=min(ans,res+tv);
edge[i].val=tv;
edge[i+1].val=tv;
}
printf("Case #%d: ",++cnt);
if(ans==inf)
printf("0\n");
else
printf("%d\n",ans);
}
return 0;
}
解法2:\(MST+LCA\)
最短的环除去一条边后一定是在这个图的最小生成树上