HDU - 6005 pandaland Dijkstra + pruning

1. Question meaning: give you n edges, let you find a ring with the least weight among them

2. Analysis: a ring must start from a point, and finally return to this point. And because every point must be in an edge, we can regard the two ends of an edge as a starting point and an end point. We only need to find the shortest path from the starting point to the end point. The final result plus the weight of this edge is the minimum weight of this ring. We can find all rings by traversing all the edges. Pay attention to add a pruning here: when the sum of the minimum weight is greater than min when the shortest path is found, exit directly.

3. Code:

#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 the current minimum sum + edge weight > global minimum: pruning
        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;//Number each point
             if(!cp[P(x2,y2)])cp[P(x2,y2)] = ++cnt;
             int s = cp[P(x1,y1)],e = cp[P(x2,y2)];//starting point, end point
             addEdge(s,e,c);
             addEdge(e,s,c);
             node[i].from = s;node[i].to = e;node[i].v = c;//Save each edge
        }
        minn = INF;
        for(int i = 0;i<m;i++){//Loop each edge
            memset(dist,INF,sizeof(dist));
            Dijkstra(node[i].from,node[i].to,node[i].v);//shortest path
            if(dist[node[i].to]!=INF)minn = min(minn,dist[node[i].to] + node[i].v);//To update
        }
        printf("Case #%d: %d\n",t,minn>=INF?0:minn);
    }
    return 0;
}

 

Posted by freephoneid on Sat, 21 Dec 2019 08:10:44 -0800