博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【拆点费用流】【HDU1853】【 Cyclic Tour】
阅读量:7294 次
发布时间:2019-06-30

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

题意:

    有N个城市,M条单向路,Tom想环游全部城市,每次至少环游2个城市,每个城市只能被环游一次。由于每条单向路都有长度,要求游遍全部城市的最小长度。

 

    // 给定一个有向图,必须用若干个环来覆盖整个图,要求这些覆盖的环的权值最小。

XD 第一次知道网络流拆点做法 但还没完全理解透,多做几题感悟感悟 ,先发一下别人题解 ,代码当然自己写

思路:

    原图每个点 u 拆为 u 和 u' ,从源点引容量为 1 费用为 0 的边到 u ,从 u' 引相同性质的边到汇点,若原图中存在 (u, v) ,则从 u 引容量为 1 费用为 c(u, v) 的边到 v' 。

    这里源模拟的是出度,汇模拟的是入度,又每个点的出度等于入度等于 1 ,那么如果最大流不等于顶点数 n ,则无解;否则,答案就是最小费用。

也可以用二分图的思想

对于满足条件的环,每个点的入度和出度均为1,我们可以把每个点拆成入点和出点,那么也就是说一个入点对应一个出点,一个出点对应一个入点。那么这个问题就变成了一个最佳匹配问题。

代码:
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define oo 0x13131313using namespace std;const int MAXN=300;const int MAXM=300000;const int INF=0x3f3f3f3f;struct Edge{ int to,next,cap,flow,cost; void get(int a,int b,int c,int d) { to=a,cap=b,cost=c;next=d;flow=0; }}edge[MAXM];int head[MAXN],tol;int pre[MAXN],dis[MAXN];bool vis[MAXN];int N;void init(int n){ N=n; tol=0; memset(head,-1,sizeof(head));}void addedge(int u,int v,int cap,int cost){ edge[tol].get(v,cap,cost,head[u]);head[u]=tol++; edge[tol].get(u,0,-cost,head[v]);head[v]=tol++;}bool spfa(int s,int t){ queue
q; for(int i=0;i
edge[i].flow&& dis[v]>dis[u]+edge[i].cost ) { dis[v]=dis[u]+edge[i].cost; pre[v]=i; if(!vis[v]) { vis[v]=true; q.push(v); } } } } if(pre[t]==-1) return false; else return true;}int minCostMaxflow(int s,int t,int &cost){ int flow=0; cost = 0; while(spfa(s,t)) { int Min=INF; for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]) { if(Min >edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; } for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; cost+=edge[i].cost*Min; } flow+=Min; } return flow;}int NN,MM;void input(){ int a,b,c; for(int i=1;i<=MM;i++) { scanf("%d%d%d",&a,&b,&c); addedge(a,b+NN,1,c); }}void solve(){ int s=NN*2+1,t=NN*2+2,k,ANS; for(int i=1;i<=NN;i++) { addedge(s,i,1,0); addedge(i+NN,t,1,0); } k=minCostMaxflow(s,t,ANS); if(k==NN) printf("%d\n",ANS); else printf("-1\n");}void File(){ freopen("a.in","r",stdin); freopen("a.out","w",stdout);}int main(){ // File(); while(cin>>NN>>MM) { init(MAXN); input(); solve(); } return 0;}

转载于:https://www.cnblogs.com/zy691357966/p/5480385.html

你可能感兴趣的文章
node.js调试
查看>>
集成学习原理小结
查看>>
中国的程序员们是否要声援微软小冰?
查看>>
字体网站
查看>>
AgileEAS.NET平台开发实例-药店系统-报表开发(上)
查看>>
3 weekend110的hadoop中的RPC框架实现机制 + hadoop中的RPC应用实例demo
查看>>
《高效程序员的修炼》 读书笔记
查看>>
Nature:中国正在上演AI人才争夺战,中国公司在与Google竞争
查看>>
VS代码提示不出现或者提示变成英文或者各种奇葩问题的解决
查看>>
WGS 1984 Web Mercator 对于在线地图服务的意义
查看>>
Word2vec 讨论
查看>>
HBase编程 API入门系列之put(客户端而言)(1)
查看>>
percona-toolkit之pt-kill:杀掉mysql查询或连接
查看>>
JavaScriptSerializer 对json数据转换
查看>>
重裝系統,磁盤消失解決方法
查看>>
11.13. Highslide
查看>>
Visual Studio 11 Beta 带来新的Metro 应用开发体验
查看>>
最佳实践: 勿在 Servlet 中实现 SingleThreadModel
查看>>
IIS发生意外错误0x8ffe2740
查看>>
架构设计中服务层的简单理解
查看>>