ccf 201812-5
Posted shiliuxinya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ccf 201812-5相关的知识,希望对你有一定的参考价值。
题解:最小费用可行流
有bug,处理一部分数据的时候会死循环,先码着
#include <stdio.h> #include <string.h> #include <queue> #define INF 0x3f3f3f3f #define MAX 205 #define MAX_EDG 505 using namespace std; typedef struct Node{ int to; //边的终点 int cap; //当前最大容量 int cost; //单位流量的费用 int next; //相同起点的下一条边在map中的编号(位置) }Node; Node map[MAX_EDG*2]; //存边:正向边 + 反向边 int vis[MAX]; int dis[MAX]; //s到第i个顶点的最小代价 int pre[MAX]; int flow[MAX]; //s到第i个顶点可更新的最大流量 int head[MAX]; //第i个顶点的第一条边在map中的位置 int count; //计数,第几个顶点 int n,m,s,t; int max_flow, min_cost; //最大流 最小费用 int du[MAX]; //记录顶点的出入度 queue<int> q; void add_edge(int from, int to, int cap, int cost){ //from起点 to终点 cap当前容量 cost单位费用 map[count].to=to; map[count].cap=cap; map[count].cost=cost; map[count].next=head[from]; head[from]=count++; //更新count } bool spfa(int s, int t){ memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); q.push(s); vis[s]=1; dis[s]=0; flow[s]=INF; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; //为什么 for(int i=head[u] ;i!=-1; i=map[i].next){ //i是边在map中的编号 if(!map[i].cap) continue; //当前边没有可增加的容量了,就跳过 int v=map[i].to; int w=map[i].cost; if(dis[v] > dis[u] + w) { dis[v]=dis[u]+w; flow[v]=min(flow[u],map[i].cap); //取到边的起点u可更新的流量和这条边的剩余容量的最小值 pre[v]=i; // if(!vis[v]){ vis[v]=1; q.push(v); } } } } return dis[t]!=INF; // } int MFMC(int s, int t){ // while(spfa(s,t)){ //还存在增广路 int x= t; max_flow+=flow[t]; min_cost+=flow[t]*dis[t]; while(x!=s){ //遍历增广路 //bug:这里会死循环 printf("x!=s "); int i=pre[x]; map[i].cap-=flow[t]; //正向弧减 map[i^1].cap+=flow[t]; //反向弧加 x=map[i^1].to; } } } int main(){ //最小费用可行流 int T,u,v,e; char type; int num,sum; while(scanf("%d %d %d",&T,&s,&e)!=EOF){ //此处的s没有用 for(int i=0;i<T;i++){ scanf("%d %d",&n,&m); memset(head,-1,sizeof(head)); memset(du,0,sizeof(du)); s=0; t=n+1; count=0; num=0; sum=0; max_flow=min_cost=0; for(int j=0;j<m;j++){ scanf("%d %d %c",&u,&v,&type); if(type==‘A‘){ //A:流量上界是INF,下界是1,容量是INF-1=INF add_edge(u,v,INF,e); add_edge(v,u,0,-e); du[u]--; //u流出 du[v]++; //v流入 num+=e; } else if(type==‘B‘){ //B:流量上界为1,下界也是1,所以容量为1-1=0 du[u]--; //容量0,不建边 du[v]++; num+=e; } else if(type==‘C‘){ //C:流量上界为INF,下界为0,所以容量=INF add_edge(u,v,INF,e); add_edge(v,u,0,-e); } else{ //D:流量上界是1,下界是0,所以容量是1 add_edge(u,v,1,e); add_edge(v,u,0,-e); } } for(int j=1;j<=n;j++){ if(du[j]>0){ //流入大于流出 sum+=du[j]; add_edge(s,j,du[j],0); //和s点相连 } else if(du[j]<0){ //流出大于流入 add_edge(j,t,-du[j],0); //和t点相连 } } printf("MACF 前 "); MFMC(s,t); printf("MfMC 后 "); if(max_flow!=sum) printf("-1 "); else printf("%d ",min_cost+num); } } return 0; }
以上是关于ccf 201812-5的主要内容,如果未能解决你的问题,请参考以下文章