题意对我这种英语大(渣)神(渣)来说挺难理解的。
简单的说下题意(按输入输出来讲,前面的描述一堆的rubbish,还用来误导人),给你n个点,其中有np个是能提供电力的点,nc个是能消费电力的点,剩下的点(n-np-nc)是中转战即不提供电力也不消费电力,点与点之间是有线路存在的,有m条线路,每条线路有最多运载限定。
前4个数据就是有n个点,np个供电点,nc个消费点,m条线路,接来题目先给出的是m条线路的数据,(起点,终点)最多运载量,然后是np个供电点的数据(供电点)最多供电量,接着就是nc个消费点的数据(消费点)最多消费电量。
题目要我们求出给定的图最大能消费的总电量(就是求最大流)
其实我开始用的是Ford-Fulkerson算法,超时了,dinic就是对于Ford-Fulkerson算法进行一个优化,不去搜索那些不可能的点,搜索之前进行一次广搜处理,
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include <string.h>
#include <math.h>
#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
const int max_V=109;
struct edge
{
int to,cap,rev;//终点 容量 反向边
};
vector<edge> G[max_V];
int level[max_V];//顶点到源点的距离标号
int iter[max_V];//当前弧,在其之前的边已经没有用了
void add_edge(int from ,int to, int cap)
{
G[from].push_back((edge){to,cap,G[to].size()});
G[to].push_back((edge){from,0,G[from].size()-1});
}
void bfs(int s)
{
memset(level,-1,sizeof(level));
queue<int > que;
level [s]=0;
que.push(s);
while(!que.empty())
{
int v=que.front();
que.pop();
for(int i=0;i<G[v].size();i++)
{
edge &e=G[v][i];
if(e.cap>0&&level[e.to]<0)
{
level[e.to]=level[v]+1;
que.push(e.to);
}
}
}
}
//深搜找增广路
int dfs(int v,int t,int f)
{
if(v==t)return f;
for(int &i=iter[v];i<G[v].size();i++)
{
edge &e=G[v][i];
if(e.cap>0&&level[v]<level[e.to])
{
int d=dfs(e.to,t,min(f,e.cap));
if(d>0)
{
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow(int s,int t)//最大流求解
{
int flow = 0;
while(1)
{
bfs(s);
if(level[t]<0)return flow;
memset(iter,0,sizeof(iter));
int f;
while((f=dfs(s,t,1000000))>0)
{
flow+=f;
}
}
}
int main()
{
int u,v,cc;
int n,np,nc,m;
while(~scanf("%d%d%d%d",&n,&np,&nc,&m))
{
//节点数,发电站数,电厂数,电力传输线数目
int s=n+1,t=n+2;
for(int i=0;i<max_V;i++)G[i].clear();
for(int i=1;i<=m;i++)
{
while(getchar()!='(');
scanf("%d,%d)%d",&u,&v,&cc);
add_edge(u,v,cc);
}
for(int i=1;i<=np;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&cc);
add_edge(s,u,cc);
}
for(int i=1;i<=nc;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&cc);
add_edge(u,t,cc);
}
printf("%d\n",max_flow(s,t));
}
return 0;
}
Ford-Fulkerson算法:超时了,不是说应该会很快吗。。。
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include <string.h>
#include <math.h>
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
const int max_V=109;
struct edge
{
int to,cap,rev;//终点 容量 反向边
};
vector<edge> G[max_V];
bool used[max_V];
void add_edge(int from ,int to, int cap)
{
G[from].push_back((edge){to,cap,G[to].size()});
G[to].push_back((edge){from,0,G[from].size()-1});
}
//深搜找增广路
int dfs(int v,int t,int f)
{
if(v==t)return f;
used[v]=true;
for(int i=0;i<G[v].size();i++)
{
edge &e=G[v][i];
if(!used[e.to]&&e.cap>0)
{
int d=dfs(e.to,t,min(f,e.cap));
if(d>0)
{
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow(int s,int t)//最大流求解
{
int flow = 0;
while(1)
{
memset(used,0,sizeof(used));
int f=dfs(s,t,1000000);
if(f==0)return flow;
flow+=f;
}
}
int main()
{
int u,v,cc;
int n,np,nc,m;
while(~scanf("%d%d%d%d",&n,&np,&nc,&m))
{
//节点数,发电站数,电厂数,电力传输线数目
int s=n+1,t=n+2;
for(int i=0;i<max_V;i++)G[i].clear();
for(int i=1;i<=m;i++)
{
while(getchar()!='(');
scanf("%d,%d)%d",&u,&v,&cc);
add_edge(u,v,cc);
}
for(int i=1;i<=np;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&cc);
add_edge(s,u,cc);
}
for(int i=1;i<=nc;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&cc);
add_edge(u,t,cc);
}
printf("%d\n",max_flow(s,t));
}
return 0;
}