博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu3488 / hdu3435 / hdu1853 最小费用最大流 圈 拆点
阅读量:5035 次
发布时间:2019-06-12

本文共 3121 字,大约阅读时间需要 10 分钟。

  题目大意:

    在一个有向图中,求经过所有点的最小圈。

  思路:

    (如果是用二分图的完美匹配来做,那么直接上模版就好了)。

    用最小费用最大流的思路如下:

    首先是每个点都只能走一次,限制的点容量是用拆点来完成的。把i点拆为i和i+n两个点,建边i->i+n,这样i这个点负责入边,i+n点负责出边。这样不管有多少边与i相连,只能走一次i点。

    每个点都必须走。源点S(2*n+1)连向i, 容量为1,边权为0。i+n连向汇点E(2*n+2),容量为1,边权为0。对于输入的边a,b,w,建立a->b+n的边,容量为1,边权为w。

    然后就是用模版。这样下来,会发现,完美匹配的做法与最小流最大流的做法其实是一样的。完美匹配就是每个点必须且仅走一次,在这里可以理解为满流。

1 #include
2 #include
3 #include
4 #include
5 using namespace std; 6 7 const int N =1010, M=50010,INF=0x3f3f3f3f; 8 struct node 9 { 10 int to, next, c ,f;//c是容量,f是费用 11 }edge[M]; 12 int head[N],dis[N],load[N],p[N]; 13 bool vis[N]; 14 int tot,flow,cost; 15 bool spfa(int S, int E,int n) 16 { 17 int que[N*10],qout,qin; 18 memset(vis,0,sizeof(vis)); 19 memset(load,-1,sizeof(load)); 20 memset(p,-1,sizeof(p)); 21 for(int i=0;i<=n;i++) 22 dis[i]=INF; 23 qin=qout=0; 24 que[qin++]=S; 25 dis[S]=0; 26 vis[S]=1; 27 while(qin!=qout) 28 { 29 int u=que[qout++]; 30 vis[u]=0; 31 for(int i=head[u];i!=-1;i=edge[i].next) 32 { 33 if(edge[i].c) 34 { 35 int v=edge[i].to; 36 if(dis[v]-dis[u]>edge[i].f) 37 { 38 dis[v]=dis[u]+edge[i].f; 39 p[v]=u; 40 load[v]=i; 41 if(!vis[v]) 42 { 43 vis[v]=1; 44 que[qin++]=v; 45 } 46 } 47 } 48 } 49 } 50 if(dis[E]==INF) return 0; 51 return 1; 52 } 53 void MCF(int S, int E,int n) 54 { 55 int u,mn; 56 flow=cost=0; 57 while(spfa(S,E,n)) 58 { 59 u=E; mn=INF; 60 while(p[u]!=-1) 61 { 62 mn=min(edge[load[u]].c, mn); 63 u=p[u]; 64 } 65 u=E; 66 while(p[u]!=-1) 67 { 68 edge[load[u]].c-=mn; 69 edge[load[u]^1].c+=mn; 70 u=p[u]; 71 } 72 cost+=dis[E]*mn; 73 flow+=mn; 74 } 75 } 76 void addedge(int a,int b,int c,int d) 77 { 78 edge[tot].to=b;edge[tot].c=c;edge[tot].f=d; 79 edge[tot].next=head[a];head[a]=tot++; 80 edge[tot].to=a;edge[tot].c=0;edge[tot].f=-d; 81 edge[tot].next=head[b];head[b]=tot++; 82 } 83 void init() 84 { 85 tot=0; 86 memset(head,-1,sizeof(head)); 87 } 88 int main() 89 { 90 //freopen("test.txt","r",stdin); 91 int n,m,k,i,j,w,cas,s,e; 92 scanf("%d",&cas); 93 while(cas--) 94 { 95 init(); 96 scanf("%d%d",&n,&m); 97 s=2*n+1;e=s+1; 98 while(m--) 99 {100 scanf("%d%d%d",&i,&j,&w);101 addedge(i,j+n,1,w);102 }103 for(i=1;i<=n;i++){104 addedge(s,i,1,0);105 addedge(i+n,e,1,0);106 }107 MCF(s,e,e);108 printf("%d\n",cost);109 }110 return 0;111 }
View Code

 

 

转载于:https://www.cnblogs.com/Potato-lover/p/3980109.html

你可能感兴趣的文章
CSS清除浮动方法
查看>>
JVM内存回收机制简述
查看>>
洛咕 P2480 [SDOI2010]古代猪文
查看>>
js-创建对象的几种方式
查看>>
JDK JRE Java虚拟机的关系
查看>>
2018.11.20
查看>>
word20161215
查看>>
12th week blog
查看>>
dijkstra (模板)
查看>>
python小记(3)
查看>>
编译Linux驱动程序 遇到的问题
查看>>
大型分布式网站架构技术总结
查看>>
HDU 1017[A Mathematical Curiosity]暴力,格式
查看>>
[算法之美] KMP算法的直观理解
查看>>
EntityFramework 性能优化
查看>>
Django Rest Framework--2
查看>>
java.lang.NullPointerException - 如何处理空指针异常
查看>>
Python学习-文件操作
查看>>
ACCP8.0Y2Web前端框架与移动应用开发第2章Bootstrap样式
查看>>
框架更新 (简)
查看>>