• Mining Station on the Sea (hdu 2448 SPFA+KM)


    Mining Station on the Sea

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


    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 s2448eabed 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
     

    Source
     

    Recommend
    gaojie   |   We have carefully selected several similar problems for you:  2454 2452 2451 2447 2453 
     


    题意:有m个海上基站。n个港湾。如今有n仅仅船在n个基站里,基站与基站之间有通讯的船才干够走这条路,告诉基站之间的距离,基站与港湾的距离。如今船要回到港湾,一个港湾仅仅能停靠一仅仅船,并且一旦进去就不能出来了。求全部船都回到港湾要走的最短距离之和。

    思路:先用最短路求出每一个船的起始点到每一个港湾的最短距离,而且连边,然后求二分图的最小权匹配。用KM算法。费用流也能够做,但我姿势不够优美超时了。。


    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <string>
    #include <map>
    #include <stack>
    #include <vector>
    #include <set>
    #include <queue>
    #pragma comment (linker,"/STACK:102400000,102400000")
    #define mod 1000000009
    #define INF 0x3f3f3f3f
    #define pi acos(-1.0)
    #define eps 1e-6
    #define lson rt<<1,l,mid
    #define rson rt<<1|1,mid+1,r
    #define FRE(i,a,b)  for(i = a; i <= b; i++)
    #define FREE(i,a,b) for(i = a; i >= b; i--)
    #define FRL(i,a,b)  for(i = a; i < b; i++)
    #define FRLL(i,a,b) for(i = a; i > b; i--)
    #define mem(t, v)   memset ((t) , v, sizeof(t))
    #define sf(n)       scanf("%d", &n)
    #define sff(a,b)    scanf("%d %d", &a, &b)
    #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
    #define pf          printf
    #define DBG         pf("Hi
    ")
    typedef long long ll;
    using namespace std;
    
    const int N=350;
    const int MAXM = 1000000;
    
    struct Edge{
        int u,v,len,next;
    }edge[MAXM];
    
    int n,m,k,p,num;
    int dis[N],head[N];
    bool inq[N];
    
    int nx,ny;      //两边的点数
    int g[N][N];    //二分图描写叙述,g赋初值为-INF
    int linker[N],lx[N],ly[N];  //y 中各点匹配状态。x,y中的点的标号
    int slack[N];
    bool visx[N],visy[N];
    bool flag;
    
    void init()
    {
        num=0;
        memset(head,-1,sizeof(head));
    }
    
    void addedge(int u,int v,int len)
    {
        edge[num]={u,v,len,head[u]};
        head[u]=num++;
    }
    
    void SPFA(int s)
    {
        int i,j;
        queue<int>Q;
        memset(inq,false,sizeof(inq));
        memset(dis,INF,sizeof(dis));
        Q.push(s);
        dis[s]=0;
        inq[s]=true;
        while (!Q.empty())
        {
            int u=Q.front();Q.pop();
            inq[u]=false;
            for (int i=head[u];i+1;i=edge[i].next)
            {
                int v=edge[i].v;
                if (dis[v]>dis[u]+edge[i].len)
                {
                    dis[v]=dis[u]+edge[i].len;
                    if (!inq[v])
                    {
                        Q.push(v);
                        inq[v]=true;
                    }
                }
            }
        }
    }
    
    bool DFS(int x)
    {
        visx[x]=true;
        for (int y=0;y<ny;y++)
        {
            if (visy[y]) continue;
            int tmp=lx[x]+ly[y]-g[x][y];
            if (tmp==0)
            {
                visy[y]=true;
                if (linker[y]==-1||DFS(linker[y]))
                {
                    linker[y]=x;
                    return true;
                }
            }
            else if (slack[y]>tmp)
                slack[y]=tmp;
        }
        return false;
    }
    
    int KM()
    {
        flag=true;
        memset(linker,-1,sizeof(linker));
        memset(ly,0,sizeof(ly));
        for (int i=0;i<nx;i++) //赋初值。lx置为最大值
        {
            lx[i]=-INF;
            for (int j=0;j<ny;j++)
            {
                if (g[i][j]>lx[i])
                    lx[i]=g[i][j];
            }
        }
        for (int x=0;x<nx;x++)
        {
            for (int i=0;i<ny;i++)
                slack[i]=INF;
            while (true)
            {
                memset(visx,false,sizeof(visx));
                memset(visy,false,sizeof(visy));
                if (DFS(x)) break;
                int d=INF;
                for (int i=0;i<ny;i++)
                    if (!visy[i]&&d>slack[i])
                        d=slack[i];
                for (int i=0;i<nx;i++)
                    if (visx[i])
                        lx[i]-=d;
                for (int i=0;i<ny;i++)
                {
                    if (visy[i])
                        ly[i]+=d;
                    else
                        slack[i]-=d;
                }
            }
        }
        int res=0;
        for (int i=0;i<ny;i++)
        {
            if (linker[i]==-1||g[linker[i]][i]<=-INF) //有的点不能匹配的话return-1
            {
                flag=false;
                continue;
            }
            res+=g[linker[i]][i];
        }
        return res;
    }
    //记得nx和ny初始化!!!。!

    !!

    ! int start[N]; int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin); #endif int i,j,u,v,cost; while (~scanf("%d%d%d%d",&n,&m,&k,&p)) { init(); nx=n; ny=n; for (i=0;i<n+m+10;i++) for (j=0;j<n+m+10;j++) g[i][j]=-INF; for (i=1;i<=n;i++) sf(start[i]); for (i=0;i<k;i++) { sfff(u,v,cost); addedge(u,v,cost); //网站之间的便能够走多次 addedge(v,u,cost); } for (i=0;i<p;i++) { sfff(u,v,cost); addedge(v,u+m,cost); //注意这里是单向边,由于港口仅仅进不出 } for (i=1;i<=n;i++) { SPFA(start[i]); //SPFA求出每一个船起始位置到港湾的最短距离 for (j=1;j<=n;j++) { if (dis[j+m]!=INF) g[i-1][j-1]=-dis[j+m]; // else // g[i-1][j-1]=0; } } int ans=KM(); printf("%d ",-ans); } return 0; }




  • 相关阅读:
    SpringBoot单元测试:1分钟学会单元测试
    Vite项目无法通过IP+端口的方式访问开发服务
    Element修改弹窗类组件的层级
    2022蓝桥杯A组题解
    单源最短路径
    【校招VIP】产品分析之功能分析
    【校招VIP】产品分析之活动策划宣传
    双非一本想逆袭进大厂,怎么才能打败985/211?
    【java校招你不知道的那些事儿】java校招分层级,找准定位很重要
    互联网大厂疯狂裁员,原因竟是……校招学生该如何最大程度规避风险?
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6979362.html
Copyright © 2020-2023  润新知