[省选前题目整理][LA 2197]Paint the Roads(费用流)
2015-03-28 11:44
381 查看
题目链接
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11338题目大意
给一个nn个点、mm条带权有向边的图,要你给其中的一些边涂上颜色,一条边涂颜色的代价是这条边的边权,要使得最终每个点都在kk个带颜色的环上,求最小付出代价,若无解输出−1-1。思路
可以看成是在一个带权有向图中选若干条边,使得每个点都在kk个环上,求选的所有边的最小边权之和。观察一个点,若它在kk个环上,则它的入度和出度均等于kk。如下图是k=2k=2的情况。那么一个很显然的思路就出来了。将每个点ii拆成两个点ii和i+ni+n。分别从SS向ii、i+ni+n向TT连容量为kk、费用为00的边(代表限制每个点的入度和出度最多等于kk),对于每条边u−>vu->v而言,从uu向v+nv+n连容量为11、费用为该边边权的边(表示选择该边可以给uu增加11个出度、给vv增加一个入度,并付出该边边权的代价)。那么如果有解的话,这个图的最大流必为n∗kn*k(每个点的入度和出度都是kk),最小费用即为答案。
代码
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define MAXV 1000 #define MAXE 1000000 #define INF 0x3f3f3f3f using namespace std; int n,m,S,T; struct edge { int u,v,w,cap,next; }edges[MAXE]; int head[MAXV],nCount=0; void AddEdge(int U,int V,int W,int C) { edges[++nCount].u=U; edges[nCount].v=V; edges[nCount].w=W; edges[nCount].cap=C; edges[nCount].next=head[U]; head[U]=nCount; } void add(int U,int V,int W,int C) { AddEdge(U,V,W,C); AddEdge(V,U,-W,0); } int dist[MAXV],q[MAXE*2],pre[MAXV]; bool inQueue[MAXV]; bool SPFA() { memset(inQueue,false,sizeof(inQueue)); memset(pre,-1,sizeof(pre)); memset(dist,INF,sizeof(dist)); int h=0,t=1; q[h]=S; dist[S]=0; inQueue[S]=true; while(h<t) { int u=q[h++]; inQueue[u]=false; for(int p=head[u];p!=-1;p=edges[p].next) { int v=edges[p].v; if(dist[u]+edges[p].w<dist[v]&&edges[p].cap) { dist[v]=dist[u]+edges[p].w; pre[v]=p; if(!inQueue[v]) { inQueue[v]=true; q[t++]=v; } } } } return pre[T]!=-1; } int MCMF(int &maxflow) { int cost=0; while(SPFA()) { int flow=INF; for(int p=pre[T];p!=-1;p=pre[edges[p].u]) flow=min(flow,edges[p].cap); for(int p=pre[T];p!=-1;p=pre[edges[p].u]) { edges[p].cap-=flow; edges[p^1].cap+=flow; } cost+=flow*dist[T]; maxflow+=flow; } return cost; } int main() { int TestCase; scanf("%d",&TestCase); while(TestCase--) { int K; memset(head,-1,sizeof(head)); nCount=1; S=MAXV-2,T=MAXV-1; scanf("%d%d%d",&n,&m,&K); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); u++,v++; //!!!!输入的点是以0开始的 add(u,v+n,w,1); } for(int i=1;i<=n;i++) { add(S,i,0,K); add(i+n,T,0,K); } int maxflow=0; int cost=MCMF(maxflow); if(maxflow!=n*K) printf("-1\n"); else printf("%d\n",cost); } return 0; }
相关文章推荐
- LA 2197 Paint the Roads 费用流
- UvaLive 2197 Paint the Roads(费用流)
- UVALive - 2197 Paint the Roads(费用流)
- UVALive 2197 Paint the Roads(费用流)
- uva 12092 Paint the Roads(费用流)
- [省选前题目整理][BZOJ 1927][SDOI 2010]星际竞速(费用流)
- 【 UVALive - 2197】Paint the Roads(上下界费用流)
- [省选前题目整理][POJ 2942]Knights of the Round Table(Tarjan求点双联通分量+DFS对环染色)
- [省选前题目整理][LA 4043]Ants(二分图最小权匹配)
- Paint the Roads UVALive - 2197
- [省选前题目整理][HDU 1028]Ignatius and the Princess III(生成函数)
- [省选前题目整理][POJ 2699]The Maximum Number of Strong Kings(暴力枚举+最大流)
- [省选前题目整理][BZOJ 1070][SCOI 2011]修车(费用流)
- [省选前题目整理][BZOJ 2324][ZJOI 2011]营救皮卡丘(费用流)
- [省选前题目整理][SPOJ CIRU]The area of the union of circles(自适应Simpson积分求圆并面积)
- [省选前题目整理][SPOJ OPTM]Optimal Marks(最小割)
- [省选前题目整理][BZOJ 3680]吊打XXX(模拟退火)
- [省选前题目整理][SGU 261]Discrete Roots(扩展欧几里得+中国剩余定理+原根+大步小步算法)
- [省选前题目整理][BZOJ 2730][HNOI 2012]矿场搭建(Tarjan求割点+计数问题)
- [省选前题目整理][POJ 2069]Super Star(爬山搜索)