zoukankan      html  css  js  c++  java
  • hdu 2448(KM算法+SPFA)

    Mining Station on the Sea

    Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2997    Accepted Submission(s): 913


    Problem Description
    The ocean is a treasure house of resources and the development of human society comes to depend more and more on it. In order to develop and utilize marine resources, it is necessary to build mining stations on the sea. However, due to seabed mineral resources, the radio signal in the sea is often so weak that not all the mining stations can carry out direct communication. However communication is indispensable, every two mining stations must be able to communicate with each other (either directly or through other one or more mining stations). To meet the need of transporting the exploited resources up to the land to get put into use, there build n ports correspondently along the coast and every port can communicate with one or more mining stations directly.

    Due to the fact that some mining stations can not communicate with each other directly, for the safety of the navigation for ships, ships are only allowed to sail between mining stations which can communicate with each other directly.

    The mining is arduous and people do this job need proper rest (that is, to allow the ship to return to the port). But what a coincidence! This time, n vessels for mining take their turns to take a rest at the same time. They are scattered in different stations and now they have to go back to the port, in addition, a port can only accommodate one vessel. Now all the vessels will start to return, how to choose their navigation routes to make the total sum of their sailing routes minimal.

    Notice that once the ship entered the port, it will not come out!
     
    Input
    There are several test cases. Every test case begins with four integers in one line, n (1 = <n <= 100), m (n <= m <= 200), k and p. n indicates n vessels and n ports, m indicates m mining stations, k indicates k edges, each edge corresponding to the link between a mining station and another one, p indicates p edges, each edge indicating the link between a port and a mining station. The following line is n integers, each one indicating one station that one vessel belongs to. Then there follows k lines, each line including 3 integers a, b and c, indicating the fact that there exists direct communication between mining stations a and b and the distance between them is c. Finally, there follows another p lines, each line including 3 integers d, e and f, indicating the fact that there exists direct communication between port d and mining station e and the distance between them is f. In addition, mining stations are represented by numbers from 1 to m, and ports 1 to n. Input is terminated by end of file.

     
    Output
    Each test case outputs the minimal total sum of their sailing routes.
     
    Sample Input
    3 5 5 6 1 2 4 1 3 3 1 4 4 1 5 5 2 5 3 2 4 3 1 1 5 1 5 3 2 5 3 2 4 6 3 1 4 3 2 2
     
    Sample Output
    13
     
    题意:现在有m个油井和n个港口(n<=m),现在有n条船停在这些油井这里,第一行输入n个数, 输入IDX[i]代表第i条船停在 IDX[i]这个油井这里,然后接下来有k行,输入u,v,w代表油井u和油井v之间的距离为w,然后又p行,代表了港口和油井之间的距离,现在这些船全部要回到港口,而且每个港口只能停一艘船,问这些船返回港口的最短距离。
    题解:开始的时候建边,要为油田和油田建双向边,但是油田港口只能建单向边,因为回去了就不能往回走了.用spfa求出每艘船到每个港口的距离(注意编号,港口编号为 1+m~n+m),然后求出来之后进行KM算法最优匹配即可得到答案。
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    #include <stdlib.h>
    using namespace std;
    const int N = 400;
    const int INF = 999999999;
    int lx[N],ly[N];
    bool visitx[N],visity[N];
    int slack[N];
    int match[N];
    int graph[N][N];
    int idx[N]; ///船所在的油井下标
    int n,m,k,p;
    bool Hungary(int u)
    {
        visitx[u] = true;
        for(int i=m+1; i<=m+n; i++)
        {
            if(!visity[i])
            {
                int temp = lx[u]+ly[i]-graph[u][i];
                if(temp==0)
                {
                    visity[i] = true;
                    if(match[i]==-1||Hungary(match[i]))
                    {
                        match[i] = u;
                        return true;
                    }
                }
                else
                {
                    slack[i] = min(slack[i],temp);
                }
            }
        }
        return false;
    }
    void KM()
    {
        memset(match,-1,sizeof(match));
        memset(ly,0,sizeof(ly));
        for(int i=1; i<=n; i++) ///定标初始化
        {
            lx[idx[i]] = -INF;
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=m+1; j<=n+m; j++)
            {
                lx[idx[i]] = max(lx[idx[i]],graph[idx[i]][j]);
            }
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=m+1; j<=m+n; j++) slack[j] = INF;
            while(true)
            {
                memset(visitx,false,sizeof(visitx));
                memset(visity,false,sizeof(visity));
                if(Hungary(idx[i])) break;
                else
                {
                    int temp = INF;
                    for(int j=1+m; j<=n+m; j++)
                    {
                        if(!visity[j]) temp = min(temp,slack[j]);
                    }
                    for(int j=1; j<=n; j++)
                    {
                        if(visitx[idx[j]]) lx[idx[j]]-=temp;
                    }
                    for(int j=1; j<=n+m; j++)
                    {
                        if(visity[j]) ly[j]+=temp;
                        else slack[j]-=temp;
                    }
                }
            }
        }
    }
    struct Edge
    {
        int v,w,next;
    } edge[N*N];
    int head[N],tot;
    void init()
    {
        memset(head,-1,sizeof(head));
        tot = 0;
    }
    void addEdge(int u,int v,int w,int &k)
    {
        edge[k].v = v,edge[k].w = w,edge[k].next = head[u],head[u] = k++;
    }
    int low[N];
    bool vis[N];
    void spfa(int s)
    {
        for(int i=1; i<=n+m; i++)
        {
            low[i] = INF;
            vis[i] = false;
        }
        queue<int> q;
        low[s] = 0;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i=head[u]; i!=-1; i=edge[i].next)
            {
                int v = edge[i].v,w = edge[i].w;
                if(low[v]>low[u]+w)
                {
                    low[v] = low[u]+w;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        for(int i=1+m; i<=n+m; i++)
        {
            if(low[i]!=INF)
            {
                graph[s][i] = -low[i];
            }
        }
    }
    int main()
    {
        while(scanf("%d%d%d%d",&n,&m,&k,&p)!=EOF)
        {
            init();
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&idx[i]);
            }
            /**油田 1-m,港口 m+1-m+n*/
            for(int i=1; i<=k; i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                addEdge(u,v,w,tot);
                addEdge(v,u,w,tot);
            }
            for(int i=1; i<=p; i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                addEdge(v,u+m,w,tot); ///油井向港口添加单向边
            }
            memset(graph,0,sizeof(graph));
            for(int i=1; i<=n; i++)
            {
                spfa(idx[i]);
            }
            KM();
            int ans = 0;
            for(int i=1+m; i<=n+m; i++)
            {
                if(match[i]!=-1)
                {
                    ans+=graph[match[i]][i];
                }
            }
            printf("%d
    ",-ans);
        }
    }
  • 相关阅读:
    IDEA报错 Unable to open debugger port (127.0.0.1:63342): java.net.BindException "Address already in use
    解决Xshell 连接Linux 窗口不活动会自动断开连接
    Spring整合ActiveMQ实现消息延迟投递和定时投递
    JAVA获取某年(当年)的第一天的开始时刻和某年(当年)的最后一天的最后时刻
    将电脑信息上传到中国移动ONENET平台
    二分查找
    jcraft--SFTP demo
    org.apache.commons.io.Charsets
    oracle中的替换函数replace和translate函数
    Java中getResourceAsStream的用法
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5734502.html
Copyright © 2011-2022 走看看