最小路径覆盖问题
来源:互联网 发布:淘宝芝士年糕哪家好吃 编辑:程序博客网 时间:2024/04/19 17:45
题目参考 COGS 728【网络流24题】最小路径覆盖问题。。。
大意是给你一个有向图,要求你使每一个点在且仅在一条路径上,如果路径总数最少,则这个方案成为最小路径覆盖。
1、网络流解法
既然是网络流24题,我们首先考虑一下网络流的做法。参考SDOI 星际竞速,我们把每个点拆为两个点,源点向第一排点连边,汇点向第二排点两边,原图中的边由第一排点向第二排点连,跑一遍最大流,点数减去流量maxflow即为路径数,因为这样只有源点到maxflow个路径终点的边剩余流量为1(同样的,只有maxflow个路径起点到汇点剩余流量为1),这样,我们在做网络流的时候,每找到一条增广路径,我们就记录一下它是由那个点的第一排点连过来。跑完最大流后,递归输出路径即可。code:
#include<iostream>#include<cstdio>#include<cstring>using namespace std;struct hp{int u,v,c;}a[130000];int point[500],next[130000],n,m,e,t;int cur[500],pre[500],lev[500],gap[500],pred[500];bool f[200]={false};void add(int x,int y,int c){e++; next[e]=point[x]; cur[x]=point[x]=e;a[e].u=x; a[e].v=y; a[e].c=c;e++; next[e]=point[y]; cur[y]=point[y]=e;a[e].u=y; a[e].v=x; a[e].c=0;}int ISAP(int vs,int vt){int u,v,i,minl,aug,maxt=0; bool f;u=vs; gap[0]=vt-vs+1;while (lev[vs]<vt) { f=false;for (v=cur[u];v!=0;v=next[v]) if (lev[u]==lev[a[v].v]+1&&a[v].c>0) {f=true; cur[u]=v; break;}if (f) { pre[a[v].v]=v; u=a[v].v; if (u==vt) { aug=2100000000; for (i=v;i!=0;i=pre[a[i].u]) if (aug>a[i].c) aug=a[i].c; maxt+=aug; for (i=v;i!=0;i=pre[a[i].u]) { pred[a[i].v]=a[i].u; a[i].c-=aug; a[i^1].c+=aug; } u=vs; } }else { minl=vt; for (i=point[u];i!=0;i=next[i]) if (minl>lev[a[i].v]&&a[i].c>0) minl=lev[a[i].v]; gap[lev[u]]--; if (gap[lev[u]]==0) break; lev[u]=minl+1; cur[u]=point[u]; gap[lev[u]]++; if (u!=vs) u=a[pre[u]].u; } }return maxt;}int find(int vs,int vt){ int i; for (i=point[vs];i!=0;i=next[i]) if (a[i].v==vt) return i;}int main(){int i,ii,x,y,ans,j,road[300];scanf("%d%d",&n,&m);e=1;for (i=1;i<=n;++i) { add(0,i*2-1,1); add(i*2,n*2+1,1); } for (i=1;i<=m;++i) { scanf("%d%d",&x,&y); add(x*2-1,y*2,1); } ans=ISAP(0,2*n+1); ans=0; for (i=n;i>=1;--i) if (f[i]==false) { ii=i; memset(road,0,sizeof(road)); t=1; road[t]=ii; j=find(ii*2,n*2+1); ii*=2; while (a[j].c==0&&f[ii/2]==false) { f[ii/2]=true; ii=pred[ii]; ii++; t++; road[t]=ii/2; j=find(ii,n*2+1); } f[ii/2]=true; for (j=t;j>=1;--j) printf("%d ",road[j]); printf("\n"); ans++; } printf("%d\n",ans);}2、匈牙利算法
这就是为什么此题不放在网络流学习笔记的原因了。我AC之后看了RANK 1的程序,发现似乎是二分图匹配之类的东西,后来发现这玩意儿真的可以做最小路径覆盖(貌似比网络流稍快一点,学匈牙利算法就看这篇文章好了,简单通俗易懂,大赞博主。 http://blog.csdn.net/dark_scope/article/details/8880547 code:
#include<iostream>#include<cstdio>#include<cstring>using namespace std;int cd[151][151],n,m;bool visit[151];int match[151];int go[151];bool find(int u){int i,now;for (i=1;i<=cd[u][0];++i) { now=cd[u][i]; if (!visit[now]) { visit[now]=true; if (!match[now]||find(match[now])) { match[now]=u; go[u]=now; return true; } } }return false;}int main(){int st,ans=0,i,j,x,y;scanf("%d%d",&n,&m);for (i=1;i<=m;++i) { scanf("%d%d",&x,&y); cd[x][0]++; cd[x][cd[x][0]]=y; }for (i=1;i<=n;++i) { memset(visit,false,sizeof(visit)); if (!find(i)) ans++; }for (i=1;i<=n;++i) if (!match[i]) { st=i; while (st!=0){ printf("%d ",st); st=go[st];} printf("\n"); }printf("%d\n",ans);}
0 0
- 最小路径覆盖问题
- 最小路径覆盖问题
- 最小路径覆盖问题
- 最小路径覆盖问题
- 最小路径覆盖问题
- 若干最小路径覆盖问题
- swust1738: 最小路径覆盖问题
- poj1511 最小路径覆盖问题
- luogu2764 最小路径覆盖问题
- 最小路径覆盖问题 最小路径覆盖+输出解
- 最小路径覆盖问题(最小路径覆盖)
- 最小路径覆盖问题 (网络流解法)
- 网络流3最小路径覆盖问题
- [codevs 1904] 最小路径覆盖问题
- 【网络流】最小路径覆盖问题
- poj 2594(最小路径覆盖问题)
- 最小路径覆盖问题(二分图)
- Codevs 1904 最小路径覆盖问题
- hdu 3790 最短路径问题
- Android流式布局FlowLayout的实现,Android布局的内部机制onMeasure、onLayout
- OpenCV中parallel_for 和 parallel_for_学习笔记
- tpcc-mysql 性能测试
- android tween 动画效果
- 最小路径覆盖问题
- Android尺寸标注设计大全和Android切图规范
- 数据库系统概念--(范式,存储,查询,事务,引擎)
- 窗体调用2.0
- MySQL监控工具之innotop
- 【设计模式】——模式总结
- c++ #include是怎么样工作的?
- 二分法求方程的解
- percona之tcprstat 介绍