HDU - 6005 Pandaland Dijkstra + 剪枝

1.题意:给你n条边,让你在这些边中找到一个权值最小的环

2.分析:一个环必然是从一个点出发,最后又回到这个点。又因为每个点都必然在一条边中,所以可以把一条边的两端点看为是一个起点一个终点,我们只需要求从起点到终点的最短路即可,最后结果加上这条边的权值就是这个环的最小权值。我们遍历所有的边即可求出所有的环。这里注意加一个剪枝: 当求最短路时最小的权值和已经大于min了 , 就直接退出。

3.代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef pair<int,int> P;
const int maxn = 4000 + 7;
int dist[maxn<<1],head[maxn<<1],m,cnt,tot,minn;
bool judge[maxn<<1];
struct Edge{
    int to,next,val;
}edge[maxn<<2];
struct Node{
   int from,to,v;
}node[maxn];
map<P,int> cp;
void addEdge(int a,int b,int c){
    edge[tot].to = b;edge[tot].val = c;edge[tot].next = head[a];head[a] = tot++;
}
void Dijkstra(int a,int b,int v){
    memset(judge,0,sizeof(judge));
    dist[a] = 0;
    priority_queue<P,vector<P>,greater<P> > que;
    que.push(P(0,a));
    while(!que.empty()){
        P p = que.top();
        que.pop();
        if(p.first + v > minn)break;//如果当前最小和 + 边权值 > 全局最小 : 剪枝
        if(judge[p.second])continue;
        judge[p.second] = 1;
        for(int i = head[p.second];~i;i = edge[i].next){
            if((p.second==a&&edge[i].to==b)||(p.second==b&&edge[i].to==a))continue;
            if(!judge[edge[i].to]&&dist[edge[i].to] > p.first + edge[i].val){
                dist[edge[i].to] = p.first + edge[i].val;
                que.push(P(dist[edge[i].to],edge[i].to));
            }
        }
    }
    return;
}
int main()
{
    int T;
    int t = 0;
    scanf("%d",&T);
    while(T--){
        t++;
        cp.clear();
        memset(head,-1,sizeof(head));
        scanf("%d",&m);
        cnt = tot = 0;
        for(int i = 0;i<m;i++){
             int x1,y1,x2,y2,c;
             scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
             if(!cp[P(x1,y1)])cp[P(x1,y1)] = ++cnt;//每个点赋予编号
             if(!cp[P(x2,y2)])cp[P(x2,y2)] = ++cnt;
             int s = cp[P(x1,y1)],e = cp[P(x2,y2)];//起点,终点
             addEdge(s,e,c);
             addEdge(e,s,c);
             node[i].from = s;node[i].to = e;node[i].v = c;//保存每条边
        }
        minn = INF;
        for(int i = 0;i<m;i++){//循环每条边
            memset(dist,INF,sizeof(dist));
            Dijkstra(node[i].from,node[i].to,node[i].v);//最短路
            if(dist[node[i].to]!=INF)minn = min(minn,dist[node[i].to] + node[i].v);//更新
        }
        printf("Case #%d: %d\n",t,minn>=INF?0:minn);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40772692/article/details/82930317