Pandaland HDU - 6005

本文介绍了一种用于寻找图中最小成本简单环的算法,通过枚举每条边并将其“删除”,以该边的两个端点作为起点和终点进行最短路径计算,再加回该边的成本,从而找出最小成本的环。此算法适用于解决特定类型的图论问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

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

题意:求出一个具有最小值的最小环,x1,y1,x2,y2,x1,y1,x2,y2, w分别为连个相连点的坐标以及他们之间的权值。

思路:枚举每一条边,“删除”这条边,以这两个点为起点和终点跑一遍最短路,再加上这条边的权值,最后取最小值。

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int MAXN=4123;
typedef pair<int,int>p;
struct node {
    int x1,y1,x2,y2,w;
} a[MAXN];
struct qnode {
    int v,c;
    qnode(int _v=0,int _c=0):v(_v),c(_c) {}
    bool operator <(const qnode &r)const {
        return c>r.c;
    }
};
struct Edge {
    int v,cost,id,next;
} E[MAXN*2];
bool vis[MAXN];
int dist[MAXN];
int temp,w;
int cnt,head[MAXN];
int ans;
void Dijkstra(int n,int start) {
    memset(vis,false,sizeof(vis));
    for(int i=1; i<=n; i++) dist[i]=INF;
    priority_queue<qnode>que;
    while(!que.empty()) que.pop();
    dist[start]=0;
    que.push(qnode(start,0));
    qnode tmp;
    while(!que.empty()) {
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(E[u].v+w>=ans) return;
        if(vis[u]) continue;
        vis[u]=true;
        for(int i=head[u]; i!=-1; i=E[i].next) {
            if(E[i].id==temp) continue;
            int v=E[i].v;
            int cost=E[i].cost;
            if(!vis[v]&&dist[v]>dist[u]+cost) {
                dist[v]=dist[u]+cost;
                que.push(qnode(v,dist[v]));
            }
        }
    }
}
void addge(int u,int v,int w,int id) {
    E[cnt].v=v;
    E[cnt].cost=w;
    E[cnt].id=id;
    E[cnt].next=head[u];
    head[u]=cnt++;
}
int main() {
    int t;
    int cns=1;
    scanf("%d",&t);
    while(t--) {
        memset(head,-1,sizeof(head));
        cnt=1;
        map<p,int>mp;
        int m;
        scanf("%d",&m);
        int o=0;
        for(int i=1; i<=m; i++) {
            scanf("%d%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2,&a[i].w);
            if(mp[p(a[i].x1,a[i].y1)]==0)
                mp[p(a[i].x1,a[i].y1)]=++o;
            if(mp[p(a[i].x2,a[i].y2)]==0)
                mp[p(a[i].x2,a[i].y2)]=++o;
            addge(mp[p(a[i].x1,a[i].y1)],mp[p(a[i].x2,a[i].y2)],a[i].w,i);
            addge(mp[p(a[i].x2,a[i].y2)],mp[p(a[i].x1,a[i].y1)],a[i].w,i);
        }
        ans=INF;
        for(int i=1; i<=m; i++) {
            int s=mp[p(a[i].x1,a[i].y1)],e=mp[p(a[i].x2,a[i].y2)];
            w=a[i].w;
            temp=i;
            Dijkstra(o,s);
            if(dist[e]<INF) {
                ans=min(ans,dist[e]+a[i].w);
            }
        }
        printf("Case #%d: ",cns++);
        if(ans<INF)
            printf("%d\n",ans);
        else
            printf("0\n");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值