c语言求网络最大流,最大流Dinic C语言实现(详细)--poj 3281

#define N 1000

#define MAX 0x3f3f3f3f

#define min(x,y) ((x>y)?(y):(x))//定义宏

int map[N][N];//图

int dis[N];//来表示分层图距离

int q[10000],h,r;//手工队列,h为队首,r为队尾

int source,sink;//顶点的最大编号sink,最小编号source=0

int BFS(void)

{

int i,j;

memset(dis,0xff,sizeof(dis));

dis[0]=0;

h=-1;r=0;

q[0]=0;

while(h0)

{

dis[i]=dis[j]+1;//来决定每个点与源点的距离,也就是分层。。。

q[++r]=i;

}

}

}

if(dis[sink]>0)

return 1;

else

return 0;

}

int find(int x,int low)//表示已经到了x顶点,并且此时从源点到x顶点的这一段路中可以达到的最大流量

{

int i,a=0;

if(x==sink)//如果到了汇点,返回最大流量

return low;

for(i=0;i<=sink;i++)

{

if(map[x][i]>0&&dis[i]==dis[x]+1&&(a=find(i,min(low,map[x][i]))))//这就是每一层找一个,然后接着找下一层

{

map[x][i]-=a;//正向边流量增加

map[i][x]+=a;//反向边流量减少

return a;

}

}

return 0;

}

int main()

{

int ans,tans,n,f,d,i,f_sum,d_sum,j,tmp;

while(~scanf("%d%d%d",&n,&f,&d))

{

memset(map,0,sizeof(map));

source=0;sink=2*n+f+d+1;

for(i=1;i<=f;i++)map[source][i]=1;//构建图,这道题有点特殊的构图方式

for(i=1;i<=d;i++)map[2*n+f+i][sink]=1;

for(i=1;i<=n;i++)map[f+i][f+n+i]=1;

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

{

scanf("%d%d",&f_sum,&d_sum);

for(j=1;j<=f_sum;j++)

{

scanf("%d",&tmp);

map[tmp][f+i]=1;

}

for(j=1;j<=d_sum;j++)

{

scanf("%d",&tmp);

map[f+n+i][2*n+f+tmp]=1;

}

}

ans=0;

while(BFS())

{

while(tans=find(0,0x3f3f3f3f))

ans+=tans;

}

printf("%d\n",ans);

}

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于Edmonds-Karp算法的最大流问题C语言代码: ```c #include <stdio.h> #include <string.h> #include <limits.h> #define V 6 // 判断是否存在增广路径 int bfs(int rGraph[V][V], int s, int t, int parent[]) { // 创建标记数组,并初始化为false int visited[V]; memset(visited, 0, sizeof(visited)); // 创建队列,将源点加入队列 int queue[V]; int front = 0, rear = 0; queue[rear++] = s; visited[s] = 1; parent[s] = -1; // BFS搜索 while (front != rear) { int u = queue[front++]; for (int v = 0; v < V; v++) { if (!visited[v] && rGraph[u][v] > 0) { queue[rear++] = v; visited[v] = 1; parent[v] = u; } } } // 如果终点被标记,则存在增广路径 return (visited[t] == 1); } // 计算最大流 int fordFulkerson(int graph[V][V], int s, int t) { int u, v; // 创建剩余图,并初始化为原图 int rGraph[V][V]; for (u = 0; u < V; u++) { for (v = 0; v < V; v++) { rGraph[u][v] = graph[u][v]; } } // 创建父节点数组 int parent[V]; // 初始化最大流为0 int max_flow = 0; // 搜索增广路径,并将增广路径上的最小容量添加到最大流中 while (bfs(rGraph, s, t, parent)) { int path_flow = INT_MAX; for (v = t; v != s; v = parent[v]) { u = parent[v]; path_flow = path_flow < rGraph[u][v] ? path_flow : rGraph[u][v]; } for (v = t; v != s; v = parent[v]) { u = parent[v]; rGraph[u][v] -= path_flow; rGraph[v][u] += path_flow; } max_flow += path_flow; } // 返回最大流 return max_flow; } int main() { // 创建图 int graph[V][V] = { {0, 16, 13, 0, 0, 0}, {0, 0, 10, 12, 0, 0}, {0, 4, 0, 0, 14, 0}, {0, 0, 9, 0, 0, 20}, {0, 0, 0, 7, 0, 4}, {0, 0, 0, 0, 0, 0} }; // 设置源点和汇点 int s = 0, t = 5; // 计算最大流 printf("Max Flow: %d\n", fordFulkerson(graph, s, t)); return 0; } ``` 该代码实现了一个6个节点的最大流问题,其中源点为0,汇点为5。可以根据实际情况修改节点数、连通关系等参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值