Pandaland HDU - 6005【最小环】

题意:

给出一个二维平面上的 \(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\)

最短的环除去一条边后一定是在这个图的最小生成树上

猜你喜欢

转载自www.cnblogs.com/1024-xzx/p/12514190.html
今日推荐