题意:

  一个有v个点的有向图,要从点1到点v需要找两条路径,两路径不可经过同一个点(除了1和v点)。求这两条路径的最小费用(保证有解)。

分析:

  难在建图,其他套模板。

  此图给的是超级复杂图,两个点之间有多条有向边,方向还可能是相反的。用网络流来做不能仅靠2点流来保证,因为当只有3个点,4条边都是1->2->3这样的,是不是刚好2条路径?也满足了2点流的限制。其实不能这样,要保证经过每个点1点流量,还得拆点,将2~v-1这些点都拆两个点,两点之间有条费用为0容量为1的边,这样就能保证了。然后源点1出发,汇点v结束,都是流量为2就行了。当然源点,汇点需要自己另外建。

 #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]=;
cost[s]=;
flow[s]=INF; 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_cost;
ans_cost+=cost[e];
ans_flow+=tmp; int ed=e;
while(ed!=s)
{
int t=path[ed];
edge[t].flow+=tmp;
edge[t^].flow-=tmp;
ed=edge[t].from;
}
}
} int main()
{
freopen("input.txt", "r", stdin);
int n, m, a, b, c;
while(~scanf("%d%d",&n,&m))
{
ans_cost=;
edge_cnt=;
for(int i=n+; i>=; i-- ) vect[i].clear();
memset(edge,,sizeof(edge));
for(int i=; i<n; i++)
{
add_node(i*,i*+,,,);
add_node(i*+,i*,,,);
}
for(int i=; i<m; i++)
{
scanf("%d%d%d", &a, &b, &c);
add_node(a*+, b*, c, , );
add_node(b*, a*+, -c, , );
} add_node(, *+, , , ); //源点。2点流量
add_node(*+, , , , ); add_node(n*, n*+, , , );//汇点
add_node(n*+, n*, , , ); printf("%d\n",cal(, n*+));
}
return ;
}

AC代码

最新文章

  1. win7 ins 30131 oracle 12c
  2. Nodejs进阶:核心模块https 之 如何优雅的访问12306
  3. github和bitbucket
  4. ==,equal,hasCode(),identifyHasCode()浅析
  5. 一个有趣的Ajax Hack示范
  6. F1
  7. 如何在Android SDK 下查看应用程序输出日志的方法
  8. 从零开始学android开发-项目debug
  9. 人工神经网络(Artificial Neural Networks)
  10. 在mac系统安装Apache Tomcat的详细步骤
  11. XMLSocket的bug
  12. 201521123010 《Java程序设计》第9周学习总结
  13. 解决OrangePi 耳机孔没有声音
  14. vue中的$route和$router的区别
  15. 面试简单整理之web
  16. java的线程中断
  17. 第63节:Java中的Spring MVC简介笔记
  18. 牛客练习赛35 C.函数的魔法
  19. js 获取当前的网址
  20. windows环境telnet发送命令

热门文章

  1. EasyUI + EF + MVC4 后台截图
  2. 微软职位内部推荐-SENIOR PRODUCER
  3. [转]oracle10.2.0.1下载链接
  4. unity手游之聊天SDK集成与使用一
  5. PD name 和 comment 互换
  6. dictionary 和 hashtable 区别
  7. 1059: [ZJOI2007]矩阵游戏 - BZOJ
  8. linux ubuntu删除引导 grub出现错误解决方案
  9. fork产生子进程利用pipe管道通信
  10. 使用头文件cfloat中的符号常量获知浮点类型数据的表数范围---gyy整理