hdu 2448 Mining Station on the Sea【网络费用流】

Mining Station on the Sea

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2371    Accepted Submission(s): 732

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

分析:题意:有n艘船和n个港口,m割油井,n艘船在m个油井出,油井之间有距离(双向),油井到港口有距离(单向),求所有船开到港口的最小距离,每个港口对应一艘船,路径走一次。

本题可以直接费用流建图(由于英语知识不好,加边参数加错了,坑了三小时),s连油井,t连港口,还有其它边,费用为距离。

除此之外,还可以费用流+最短行时间优化,建图方式为,s与船连接,t与港口,费用为船到各个港口的最短路。

代码示例

一【未优化】

#include<stdio.h>

#include<string.h>

#include<algorithm>

#include<iostream>

#include<queue>

#define Min(a,b) a<b?a:b

#define inf 0x3f3f3f3f

#define maxn 2000000

#define maxm 3000

using namespace std;

typedef struct

{

int from,to,next;

int val,cost;

}node;

node E[maxn];

int head[maxm],dis[maxm],visit[maxm],pre[maxm],pos[maxm],cnt;

int ho[maxm];

void init()

{

memset(head,-1,sizeof(head));

cnt=0;

}

void add(int from,int to,int val,int cost)

{

E[cnt].from=from,E[cnt].to=to,E[cnt].val=val,E[cnt].cost=cost;

E[cnt].next=head[from],head[from]=cnt++;

E[cnt].from=to,E[cnt].to=from,E[cnt].val=0,E[cnt].cost=-cost;

E[cnt].next=head[to],head[to]=cnt++;

}

bool spfa(int s,int t,int n)

{

int to,val,cost;

for(int i=0;i<=n;i++)

{

dis[i]=inf,visit[i]=0,pre[i]=-1;

}

dis[s]=0,visit[s]=1,pre[s]=s;

queue<int>Q;

Q.push(s);

while(!Q.empty())

{

int k=Q.front();

Q.pop();

visit[k]=0;

for(int i=head[k];i!=-1;i=E[i].next)

{

to=E[i].to,val=E[i].val,cost=E[i].cost;

if(val>0&&dis[k]+cost<dis[to])

{

dis[to]=dis[k]+cost;

pre[to]=k;

pos[to]=i;

if(visit[to])

continue;

visit[to]=1;

Q.push(to);

}

}

}

if(pre[t]!=-1&&dis[t]<inf)

return true;

return false;

}

int MinCostFlow(int s,int t,int n)

{

int netflow=0,costflow=0,min;

while(spfa(s,t,n))

{

min=inf;

for(int i=t;i!=s;i=pre[i])

{

min=Min(min,E[pos[i]].val);

}

netflow+=min;

costflow+=min*dis[t];

for(int i=t;i!=s;i=pre[i])

{

E[pos[i]].val-=min;

E[pos[i]^1].val+=min;

}

}

return costflow;

}

int main()

{

int n,m,k,p,s,t;

int a,b,c;

while(scanf("%d%d%d%d",&n,&m,&k,&p)!=EOF)

{

init();

for(int i=1;i<=n;i++)

scanf("%d",&ho[i]);

for(int i=0;i<k;i++)

{

scanf("%d%d%d",&a,&b,&c);

add(a,b,inf,c);

add(b,a,inf,c);

}

for(int i=0;i<p;i++)

{

scanf("%d%d%d",&a,&b,&c);

add(b,a+m,1,c);

}

s=n+m+1,t=n+m+2;

for(int i=1;i<=n;i++)

{

add(s,ho[i],1,0);

add(i+m,t,1,0);

}

printf("%d\n",MinCostFlow(s,t,t+10));

}

return 0;

}

二【优化】

#include<stdio.h>

#include<string.h>

#include<algorithm>

#include<iostream>

#include<queue>

#define Min(a,b) a<b?a:b

#define inf 0x3f3f3f3f

#define maxn 2000000

#define maxm 1000

using namespace std;

typedef struct

{

int from,to,next;

int val,cost;

}node;

node E[maxn];

int head[maxm],dis[maxm],visit[maxm],pre[maxm],pos[maxm],cnt;

void init()

{

memset(head,-1,sizeof(head));

cnt=0;

}

void add(int from,int to,int val,int cost)

{

E[cnt].from=from,E[cnt].to=to,E[cnt].val=val,E[cnt].cost=cost;

E[cnt].next=head[from],head[from]=cnt++;

E[cnt].from=to,E[cnt].to=from,E[cnt].val=0,E[cnt].cost=-cost;

E[cnt].next=head[to],head[to]=cnt++;

}

bool spfa(int s,int t,int n)

{

int to,val,cost;

for(int i=0;i<=n;i++)

{

dis[i]=inf,visit[i]=0,pre[i]=-1;

}

dis[s]=0,visit[s]=1,pre[s]=s;

queue<int>Q;

Q.push(s);

while(!Q.empty())

{

int k=Q.front();

Q.pop();

visit[k]=0;

for(int i=head[k];i!=-1;i=E[i].next)

{

to=E[i].to,val=E[i].val,cost=E[i].cost;

if(val>0&&dis[k]+cost<dis[to])

{

dis[to]=dis[k]+cost;

pre[to]=k;

pos[to]=i;

if(visit[to])

continue;

visit[to]=1;

Q.push(to);

}

}

}

if(pre[t]!=-1&&dis[t]<inf)

return true;

return false;

}

int MinCostFlow(int s,int t,int n)

{

int costflow=0,netflow=0,min;

while(spfa(s,t,n))

{

min=inf;

for(int i=t;i!=s;i=pre[i])

{

min=Min(min,E[pos[i]].val);

}

netflow+=min;

costflow+=min*dis[t];

for(int i=t;i!=s;i=pre[i])

{

E[pos[i]].val-=min;

E[pos[i]^1].val+=min;

}

}

return costflow;

}

/////////////////////fei yong liu/////////////////////////

typedef struct

{

int to,next,w;

}nodf;

nodf Es[maxn];

int heads[maxm],visits[maxm],diss[maxm],cnts;

void inits()

{

memset(heads,-1,sizeof(heads));

cnts=0;

}

void adds(int from,int to,int w)

{

Es[cnts].to=to,Es[cnts].w=w,Es[cnts].next=heads[from],heads[from]=cnts++;

}

void spfas(int s,int n)

{

int to,w;

for(int i=0;i<=n;i++)

{

diss[i]=inf,visits[i]=0;

}

diss[s]=0,visits[s]=1;

queue<int>Q;

Q.push(s);

while(!Q.empty())

{

int k=Q.front();

Q.pop();

visits[k]=0;

for(int i=heads[k];i!=-1;i=Es[i].next)

{

to=Es[i].to,w=Es[i].w;

if(diss[k]+w<diss[to])

{

diss[to]=diss[k]+w;

if(visits[to])

continue;

visits[to]=1;

Q.push(to);

}

}

}

}

//////////////////////////////////////zui duan lu///////////////////////

int ho[maxm];

int main()

{

int n,m,k,p,s,t;

int a,b,c;

while(scanf("%d%d%d%d",&n,&m,&k,&p)!=EOF)

{

for(int i=1;i<=n;i++)

scanf("%d",&ho[i]);

inits();

for(int i=1;i<=k;i++)

{

scanf("%d %d %d",&a,&b,&c);

adds(a,b,c);

adds(b,a,c);

}

for(int i=1;i<=p;i++)

{

scanf("%d%d%d",&a,&b,&c);

adds(b,a+m,c);

}

init();

s=0,t=2*n+1;

for(int i=1;i<=n;i++)

{

add(s,i,1,0);

add(i+n,t,1,0);

spfas(ho[i],n+m+100);

for(int j=1;j<=n;j++)

{

if(diss[m+j]<inf)

{

add(i,n+j,1,diss[m+j]);

}

}

}

printf("%d\n",MinCostFlow(s,t,t+10));

}

return 0;

}

时间: 2024-08-10 02:01:59

hdu 2448 Mining Station on the Sea【网络费用流】的相关文章

HDU 2448 Mining Station on the Sea 费用流

Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2123    Accepted Submission(s): 642 Problem Description The ocean is a treasure house of resources and the development o

HDU 2448 Mining Station on the Sea km

#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<map> using namespace std; const int maxn = 105; const int INF = (1<<30)-1; int g[2*maxn][2*maxn]; int f[2*maxn][2*maxn]; int lx[maxn],ly[ma

HDU 2448 Mining Station on the Sea(最小费用流+spfa,超了n次的题)

Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2572    Accepted Submission(s): 775 Problem Description The ocean is a treasure house of resources and the development

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

HDU 3376 &amp;&amp; 2686 方格取数 最大和 费用流裸题

题意: 1.一个人从[1,1] ->[n,n] ->[1,1] 2.只能走最短路 3.走过的点不能再走 问最大和. 对每个点拆点限流为1即可满足3. 费用流流量为2满足1 最大费用流,先给图取负,结果再取负,满足2 #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #include <queue> #include <set&

HDU 4975 A simple Gaussian elimination problem.(网络最大流)

http://acm.hdu.edu.cn/showproblem.php?pid=4975 A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 669    Accepted Submission(s): 222 Problem Description Drag

hdu 6118 度度熊的交易计划(可行费用流)

题目链接:hdu 6118 度度熊的交易计划 题意: 中文,说的很清楚了. 题解: 对着输入建一些图,跑一下可行费用流就行了,即当费用为正的时候就不跑了,这样就先满足了费用最小. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 namespace MCMF 6 { 7 const int N=1e5+7,inf=1e9+7; 8 int u[

HDU-2448 Mining Station on the Sea

先根据不同的起点跑最短路,记录距离,从而建立二分图求最小匹配. 一开始我求最短路的时候我把港口直接加到图中,然后发现进了港口就不能出来了,所以连接港口的边就要从双向边改成单向边…………这也搞得我n和m分不清了…… 还不如排除掉港口算最短路后再统计各艘船到各个港口的最短距离…… 然后我还傻叉地用了Dijkstra来求最短路,当然TLE咯…… 事实证明,Floyd就可以了嘛我智商跑哪里去了... #include <cstdlib> #include <cstdio> #include

HDU 4862 Jump(最大k路径覆盖 费用流)(待续)

题意:一个n*m的矩阵,需要遍历所有点,从起点出发每次只可向右或向下跳,若到达位置的数字与上一步的数字相同,则获得该数字大小的能量: 否则消耗能量:哈密顿距离减1:求可获得的最大能量: 思路:网络流之最大k路径覆盖. 源点向n*m各点建流量为1,费用为0的边: n*m各点向汇点建流量为1,费用为0的边: 新增一个起点: 源点向起点建流量为k,费用为0的边:起点向各点建流量1,费用为0的边: n*m各点间建边: 建好图后跑最小费用最大流,如果满流则存在解,否则不存在:最小费用的相反数就是所能够获得