题意:

  给若干景点,每个景点有若干单向边到达其他景点,要求规划一下公交路线,使得每个景点有车可达,并且每个景点只能有1车经过1次,公车必须走环形回到出发点(出发点走2次)。问是否存在这样的线路?若存在就给出所有公交车需要走过的路的长度,要求长度尽量小。

分析:

  这超级难发现是网络流来做的。要将每个点归结到某个环上,那么环上的点都是只有1个前驱,1个后继。如果1个前驱配1个后继,就是匹配问题了。但是这样的匹配有点混杂,所以要拆点,将1个点拆成2个,分别处于X和Y集中,然后根据有向边建图。成了带权二分图的匹配了,只是要求权最小。

  建图步骤,对于每条有向边a->b,由于b放在Y集中,编号就改变为2*b+1,而a在左边,改变为a*2,容量是1,因为只能匹配一次,费用为长度。当然肯定需要反边了!接着添加汇点,由Y集到汇点都有边,再添加源点,源点到X集都有边,他们容量都是1费用0。

 #include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=+; struct node
{
int from;
int to;
int val;
int cap;
int flow;
}edge[N*N];
int edge_cnt, ans_cost;
int flow[N], cost[N], path[N], inq[N]; vector<int> vect[N]; void add_node(int from,int to,int val,int cap,int flow)
{
edge[edge_cnt].from=from;
edge[edge_cnt].to=to;
edge[edge_cnt].val=val;
edge[edge_cnt].cap=cap;
edge[edge_cnt].flow=flow;
vect[from].push_back(edge_cnt++);
} int spfa(int s,int e)
{
deque<int> que(,s);
inq[s]=;
flow[s]=INF;
cost[s]=;
while(!que.empty())
{
int x=que.front();que.pop_front();
inq[x]=;
for(int i=; i<vect[x].size(); i++)
{
node e=edge[vect[x][i]];
if( e.cap>e.flow && cost[e.to]>cost[e.from]+e.val )
{
flow[e.to]=min(flow[e.from], e.cap-e.flow);
cost[e.to]=cost[e.from]+e.val;
path[e.to]=vect[x][i];
if(!inq[e.to])
{
inq[e.to]=;
que.push_back(e.to);
}
}
}
}
return flow[e];
} int cal(int s,int e)
{
int ans_flow=;
while(true)
{
memset(flow,,sizeof(flow));
memset(path,,sizeof(path));
memset(cost,0x7f,sizeof(cost));
memset(inq,,sizeof(inq)); int tmp=spfa(s,e);
if(!tmp) return ans_flow;
ans_flow+=tmp;
ans_cost+=cost[e];//长度 int ed=e;
while(ed!=s)
{
int t=path[ed];
edge[t].flow+=flow[e];
edge[t^].flow-=flow[e];
ed=edge[t].from;
}
}
} int main()
{
freopen("input.txt", "r", stdin);
int n, b, v;
while(scanf("%d",&n), n)
{
ans_cost=edge_cnt=;
for(int i=N-; i>=; i--) vect[i].clear();
memset(edge,,sizeof(edge)); for(int i=; i<=n; i++)
{
while(scanf("%d",&b),b)
{
scanf("%d",&v);
add_node( i*, b*+, v, , ); //编号从2~n*2+1。
add_node( b*+, i*, -v, , );
}
}
//添加汇点n*2+2,源点0
for(int i=; i<=n; i++)
{
add_node(, i*, , , );
add_node(i*, , , , );
} for(int i=; i<=n; i++)
{
add_node(i*+, n*+, , , );
add_node(n*+, i*+, , , );
} if(cal(, n*+)!=n) puts("N");
else printf("%d\n",ans_cost); }
return ;
}

AC代码

UVA 1349 Optimal Bus Route Design 最优公交路线(最小费用流,拆点)的更多相关文章

  1. UVa 1349 - Optimal Bus Route Design(二分图最佳完美匹配)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  2. UVa 1349 Optimal Bus Route Design (最佳完美匹配)

    题意:给定一个有向图,让你找出若干个图,使得每个点恰好属于一个圈,并且总的权和最小. 析:每个点都有唯一的一个圈,也就是说每一点都有唯一的后继,那么我们就可以转换成求一个图的最小权的最佳完全匹配,可以 ...

  3. UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)

    恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图, 把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配. 写的费用流..最大权完美匹配KM算法没看懂 ...

  4. UVA - 1349 D - Optimal Bus Route Design

    4. D - Optimal Bus Route Design 题意:给出n(n<=100)个点的带权有向图,找出若干个有向圈,每个点恰好属于一个有向圈.要求权和尽量小. 注意即使(u,v)和( ...

  5. UVa1349 Optimal Bus Route Design(二分图最佳完美匹配)

    UVA - 1349 Optimal Bus Route Design Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...

  6. UVA1349 Optimal Bus Route Design 拆点法+最小费用最佳匹配

    /** 题目:UVA1349 Optimal Bus Route Design 链接:https://vjudge.net/problem/UVA-1349 题意:lrj入门经典P375 给n个点(n ...

  7. UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

    题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi  ...

  8. 【uva 1349】Optimal Bus Route Design(图论--网络流 二分图的最小权完美匹配)

    题意:有一个N个点的有向带权图,要求找若干个有向圈,使得每个点恰好属于一个圈.请输出满足以上条件的最小权和. 解法:有向圈?也就是每个点有唯一的后继.这是一个可逆命题,同样地,只要每个点都有唯一的后继 ...

  9. UVA1349:Optimal Bus Route Design

    题意:给定一个有向带权图,找若干个环,使得每个点属于且仅属于一个环,要求使得环权值之和最小 题解:发现这题中每个点属于且仅属于一个环,这时候"仅"这种恰好的含义,让我们想到了匹配问 ...

随机推荐

  1. Natural Language Processing with Python - Chapter 0

    一年之前,我做梦也想不到会来这里写技术总结.误打误撞来到了上海西南某高校,成为了文科专业的工科男,现在每天除了膜ha,就是恶补CS.导师是做计算语言学的,所以当务之急就是先自学计算机自然语言处理,打好 ...

  2. 【Google Protocol Buffer】Google Protocol Buffer

    http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Google Protocol Buffer 的使用和原理 Protocol Buffers ...

  3. dive into python 读笔(1)

    chapter2 and 3: 使用Python IDE来交互式地测试表达式 编写Python程序并且从IDE运行,或者从命令行运行 导入模块及调用它们的函数 声明函数以及doc string.局部变 ...

  4. sql with递归

       with temp as ( select Id, UserId, OfficeID, RoleId, DeptId, IsDelete, IsEnd, ParentId from [dbo]. ...

  5. linux whereis which

    whereis 命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b).man说明文件(参数-m)和源代码文件(参数-s). [root@localhost ~]# whereis svn svn ...

  6. zoj 3620 Escape Time II dfs

    题目链接: 题目 Escape Time II Time Limit: 20 Sec Memory Limit: 256 MB 问题描述 There is a fire in LTR ' s home ...

  7. PAT-乙级-1011. A+B和C (15)

    1011. A+B和C (15) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 HOU, Qiming 给定区间[-231, 231 ...

  8. linq集合内部赋值

    linq集合内部赋值 比如将一个列的值,赋值给另一列 有三种方法: 1. e.Result.ToList().ForEach(n => n.IsIntermediarybool = SetIsI ...

  9. hdu 4336 Card Collector 容斥原理

    读完题目就知道要使用容斥原理做! 下面用的是二进制实现的容斥原理,详见:http://www.cnblogs.com/xin-hua/p/3213050.html 代码如下: #include< ...

  10. FF浏览器来帮助我们录制脚本

    有时我们录制一个页面的脚本,我们需要知道这个页面哪些请求是耗时最大的?这个时候FF浏览器的网络分析功能就可以派上用场了,打开火狐浏览器按F12: 点击重新载入,可以看到下面的信息: 看到最耗时的操作了 ...