一开始工人们都在0号地方仓库里,派工人到1~n-1号地方去工作不需要时间,但是工人在一个地点工作完后可以跑到另一个未开始的地点进行工作,等那个地点所需人都来齐后可以开始工作,从一个地点跑到另一个地方所需时间是欧几里得距离,现在给出每个地点的开始时间和工作时间,工人之间不能替换(不会2技能的工人不能顶替会2技能的工人),求仓库最少需要派出几个工人?
思路:分析问题后可以发现,工人之间没有任何关系,因为开始时间已经给定了,所以我们必须保证的是所有需要的人都必须在开始时间前到达,所以工人之间没有任何关系。
那么我们枚举不同技能的工人,求出某一个技能的工人完成自己的工作至少需要几个人,最后累加起来就是答案了。
不过无奈我想到这里就不会构图了 = =,真是蒟蒻。
具体的构图方式是:
首先设立超级源点s和超级汇点t
s连接所有的地点,容量为INF或者这个地点所需要的人数,费用是1(流量大小即是人数)
然后所有的地点都连向t 这样表示不考虑一个工人做完后移动到另一个地点的情况,求出来的必定是所有地方的工人数总和
那么我们现在再把地点给拆成两个点,这些点如果时间满足题目的话就连向1~n-1中对应的那个地点即可,求出能到某个地点的人数即可
具体实现可以看代码,应该不难看懂
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 1050
#define INF 999999999
#define eps 1e-8
struct Edge
{
int u,v,next,cap,cost;
} edge[N*N];
struct Node
{
double x,y,b,p;
int num[6];
}e[N];
int cnt,head[N];
char ma[55][55];
int vis[N],pp[N],d[N],sumflow;
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].cap=cap;
edge[cnt].cost=cost;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].u=v;
edge[cnt].v=u;
edge[cnt].cap=0;
edge[cnt].cost=-cost;
edge[cnt].next=head[v];
head[v]=cnt++;
}
int spfa(int s,int t,int n)
{
queueq;
memset(vis,0,sizeof(vis));
memset(pp,-1,sizeof(pp));///pp[i]表示最短路径上以i为终点的边的编号
for(int i=0; i<=n; i++)
d[i]=INF;
d[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].cap>0&&d[v]>d[u]+edge[i].cost)
{
d[v]=d[u]+edge[i].cost;
pp[v]=i;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
if(d[t]==INF) return 0;///找不到一条到终点的路
return 1;
}
int MCMF(int s,int t,int n)
{
int mincost=0,minflow,flow=0;///最大费用,路径中最小流量,总流量
while(spfa(s,t,n))///找当前的最长路
{
minflow=INF+1;
for(int i=pp[t]; i!=-1; i=pp[edge[i].u])
minflow=min(minflow,edge[i].cap);///从路径中找最小的流量
flow+=minflow;///总流量加上最小流量
for(int i=pp[t]; i!=-1; i=pp[edge[i].u])
{
edge[i].cap-=minflow;///当前边减去最小流量
edge[i^1].cap+=minflow;///反向边加上最小流量
}
mincost+=d[t]*minflow;///最小费用等于路径和*每条路径的流量(经过多少次)
}
sumflow=flow;
return mincost;
}
double dist(double x,double y,double x1,double y1)
{
return sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1));
}
int main()
{
int T,n,m;
double x,y;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
scanf("%lf %lf",&x,&y);
for(int i=1;i
你可能感兴趣的:(图论-网络流)