hdu 1853 Cyclic Tour(最小权匹配/费用流)
2013-10-31 19:18
351 查看
题意:
有N个城市,M条单向路,Tom想环游全部城市,每次至少环游2个城市,每个城市只能被环游一次。由于每条单向路都有长度,要求游遍全部城市的最小长度。
// 给定一个有向图,必须用若干个环来覆盖整个图,要求这些覆盖的环的权值最小。
思路:
原图每个点 u拆为 u和 u',从源点引容量为
1费用为 0的边到 u,从 u'引相同性质的边到汇点,若原图中存在 (u, v),则从
u 引容量为 1费用为 c(u, v)的边到 v'
这里源模拟的是出度,汇模拟的是入度,又每个点的出度等于入度等于 1,那么如果最大流不等于顶点数 n,则无解;否则,答案就是最小费用。
另一种做法 : 最小权匹配
有N个城市,M条单向路,Tom想环游全部城市,每次至少环游2个城市,每个城市只能被环游一次。由于每条单向路都有长度,要求游遍全部城市的最小长度。
// 给定一个有向图,必须用若干个环来覆盖整个图,要求这些覆盖的环的权值最小。
思路:
原图每个点 u拆为 u和 u',从源点引容量为
1费用为 0的边到 u,从 u'引相同性质的边到汇点,若原图中存在 (u, v),则从
u 引容量为 1费用为 c(u, v)的边到 v'
这里源模拟的是出度,汇模拟的是入度,又每个点的出度等于入度等于 1,那么如果最大流不等于顶点数 n,则无解;否则,答案就是最小费用。
#include<cstdio> #include<cstring> #include<map> #include<vector> #include<cmath> #include<cstdlib> #include<stack> #include<queue> #include <iomanip> #include<iostream> #include<algorithm> using namespace std ; const int N=500 ; const int M=10000 ; const int inf=1<<30 ; struct node { int u,v,c,cost,next; }edge[M<<2]; int pre ,dist ,vist ,head ; int top,maxflow ; void add(int u,int v,int c,int cost) { edge[top].u=u; edge[top].v=v; edge[top].c=c; edge[top].cost=cost; edge[top].next=head[u]; head[u]=top++; edge[top].u=v; edge[top].v=u; edge[top].c=0; edge[top].cost=-cost; edge[top].next=head[v]; head[v]=top++; } int SPFA(int s,int t,int n) { memset(vist,0,sizeof(vist)); memset(pre,-1,sizeof(pre)); int u ,v ; queue<int>q; for(int i = 0 ; i < n ; i++) dist[i]=inf ; vist[s]=1;dist[s]=0; q.push(s); while(!q.empty()) { u=q.front(); q.pop(); vist[u]=0; for(int i = head[u] ; i!=-1 ; i=edge[i].next) { v=edge[i].v; if(edge[i].c && dist[v] > dist[u]+edge[i].cost) { dist[v] = dist[u]+edge[i].cost ; pre[v]=i; if(!vist[v]) { vist[v]=1; q.push(v); } } } } if(dist[t]==inf) return 0; return 1; } int MFMC(int s,int t,int n) { int flow=0,mincost=0,minflow; while(SPFA(s,t,n)) { minflow=inf; for(int i = pre[t] ; i!=-1 ;i=pre[edge[i].u]) minflow=min(minflow,edge[i].c); for(int i = pre[t] ; i!=-1 ;i=pre[edge[i].u]) { edge[i].c -=minflow; edge[i^1].c += minflow ; } flow += minflow ; mincost += dist[t]*minflow ; } maxflow=flow ; return mincost ; } int main() { int n,m,u,v,c; while(~scanf("%d%d",&n,&m)) { top=0; memset(head,-1,sizeof(head)); int s=0,t=2*n+1; while(m--) { scanf("%d%d%d",&u,&v,&c); add(u,v+n,1,c); } for(int i = 1 ; i <= n ; i++) { add(s,i,1,0); add(i+n,t,1,0); } int ans=MFMC(s,t,t+1); if(maxflow != n) printf("-1\n"); else printf("%d\n",ans); } return 0; }
另一种做法 : 最小权匹配
#include<cstdio> #include<cstring> #include<map> #include<vector> #include<cmath> #include<cstdlib> #include<stack> #include<queue> #include <iomanip> #include<iostream> #include<algorithm> using namespace std ; const int N=500 ; const int inf=1<<30; int match ,lx ,ly ,fx ,fy ; int g ; int n,m; int dfs(int u) { fx[u]=1; for(int i = 1 ; i <= n ; i++) { if(!fy[i] && lx[u]+ly[i]==g[u][i]) { fy[i]=1; if(match[i]==-1 || dfs(match[i])) { match[i]=u; return 1; } } } return 0; } int KM_match() { int a ; for(int i = 1 ; i <= n ; i++) { lx[i]=-inf; for(int j = 1 ; j <= n ; j++) lx[i]=max(lx[i],g[i][j]); } memset(match,-1,sizeof(match)); memset(ly,0,sizeof(ly)); for(int k = 1 ; k <= n ; k++) { while(1) { memset(fx,0,sizeof(fx)); memset(fy,0,sizeof(fy)); if(dfs(k)) break ; a=inf ; for(int i = 1 ; i <= n ; i++) if(fx[i]) for(int j = 1 ; j <= n ; j++) if(!fy[j]) a=min(a,lx[i]+ly[j]-g[i][j]); for(int i = 1 ; i <= n ; i++) { if(fx[i]) lx[i] -= a ; if(fy[i]) ly[i] += a ; } } } int sum=0; for(int i = 1 ; i <= n ;i++) { if(match[i]==-1 || g[match[i]][i]==-inf) { sum=-1 ; return sum ;} sum += g[match[i]][i] ; } return -sum ; } int main() { int a,b,w; while(~scanf("%d%d",&n,&m)) { for(int i = 1 ; i <= n ; i++) for(int j = 1 ; j <= n ; j++) g[i][j]=-inf ; while(m--) { scanf("%d%d%d",&a,&b,&w); if(g[a][b] <-w) g[a][b]=-w; } int ans=KM_match(); printf("%d\n",ans); } return 0; }
相关文章推荐
- hdu 1853 Cyclic Tour 最大权值匹配 所有点连成环的最小边权和
- hdu 1853 Cyclic Tour 最大权值匹配 全部点连成环的最小边权和
- hdu 1853 Cyclic Tour(KM 最小权值匹配)
- Cyclic Tour (hdu 1853 二分图最小权问题)
- hdu-1853-Tour-最小权匹配
- hdu 1853 Cyclic Tour(最小权值和)
- HDU(1853),最小权匹配,KM
- hdu A new Graph Game (最小权匹配/费用流)
- HDU 1853--Cyclic Tour【最小费用最大流 && 有向环最小权值覆盖 】
- hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)
- HDU 1498 50 years, 50 colors(二分最大匹配之最小点覆盖)
- 匈牙利算法 hdu 1151有向图的最小路径覆盖=顶点数-最大匹配数
- 【费用流】 HDU 1853 Cyclic Tour 费用流 完备匹配(裸题)
- hdu 1054 Strategic Game 二分图的匹配,最小点覆盖数
- hdu 1853 Cyclic Tour 最小费用最大流
- hdu 1533 Going Home(KM 最小权值匹配)
- HDU 1151Air Raid 最小路径覆盖=n-最大匹配量 (第二道二分匹配)
- hdu 1533 Going Home(最小权匹配KM)
- hdu 3335 - 二分匹配求最小覆盖
- 【费用流】 HDU 1853 Cyclic Tour 费用流 完备匹配(裸题)