网络流题目

来源:互联网 发布:扛旗世界纪录 知乎 编辑:程序博客网 时间:2024/04/30 05:23
 #include<iostream>//最小费用最大流 #include<memory.h>using namespace std;const int N=100;int map[2*N+2][2*N+2];//0为源点 1-n老师 n+1-2n类型 2N+1为汇点 保留的是边的权值(费用) int flow[2*N+2][2*N+2];//流量int path[2*N+2];//记录节点i在此次增广中的前驱int n;int ans=0;void input(){ cin>>n; int x; for (int i=1;i<=n;i++)  for (int j=1;j<=n;j++)  {   cin>>x;   map[i][j+n]=x;   map[j+n][i]=-x;   flow[i][j+n]=1;  } for (int i=1;i<=n;i++)  {   map[0][i]=0;   flow[0][i]=1;  } for (int i=1;i<=n;i++)  {   map[i+n][2*n+1]=0;   flow[i+n][2*n+1]=1;  } return;}int shrtpth[2*N+2];//源点到其余点的最短路径int frm[2*N+1];//记录前驱 int Queue[5*N+1];//队列bool work()//spfa找增广路 { for (int i=0;i<=2*N+1;i++)  shrtpth[i]=-32767; shrtpth[0]=0; int R,L; R=L=1; Queue[1]=0; for (;L<=R;L++) {  for (int i=0;i<=2*n+1;i++)//枚举每次被松弛的顶点即边[Queue[L]][i]  if (flow[Queue[L]][i]>0)//存在流量  if (map[Queue[L]][i]+shrtpth[Queue[L]]>shrtpth[i])  {   shrtpth[i]=map[Queue[L]][i]+shrtpth[Queue[L]];   frm[i]=Queue[L];//记前驱    Queue[++R]=i;//i入队列  } }  if (shrtpth[2*n+1]==-32767)return false; int i=2*n+1; ans+=shrtpth[2*n+1]; while (i!=0)//每次找前驱  {  flow[frm[i]][i]--;  flow[i][frm[i]]++;  i=frm[i]; } return true;}void all_clear(){   memset(flow,0,sizeof(flow)); return;}int main(){ all_clear(); input(); while(work()); cout<<ans; return 0;}


 

原创粉丝点击