Marriage Match IV HDU3461 网络流+最短路spfa
2017-07-20 11:26
267 查看
Marriage Match IV
Do not sincere non-interference。
Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is
starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.
So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?
Input
The first line is an integer T indicating the case number.(1<=T<=65)
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.
Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads
from a to b, they are different.
At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
There may be some blank line between each case.
Output
Output a line with a integer, means the chances starvae can get at most.
Sample Input
3
7 8
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
5 7 1
6 7 1
1 7
6 7
1 2 1
2 3 1
1 3 3
3 4 1
3 5 1
4 6 1
5 6 1
1 6
2 2
1 2 1
1 2 2
1 2
Sample Output
2
1
1
题解:
本题目的实质就是最短路径计数,但是有一点需要强调的一点就是,这里的边不能重复走,否则的话,跑完spfa,一遍dfs就ok了。
在这里要求边不能走重复,所以说,我们就要用网络流的方法来做了。重点是怎么建图。
我们先用spfa求一下起点到所有点的最短路。
然后进行dfs建边,建边的时候,但d[v] == d[u] + cost的时候,表明这条边有可能构成最短路的一条路径,那么就从u向v连接一条容量为1的边。
(这里千万要注意的一点就是,走过的边要打标记,不要重复走,否则会陷入死循环)
边建立完成以后,跑一个从起点到终点的网络流就好了
代码:
#include<cstdio>
#include<iostream>
#include <cstring>
#include <queue>
using namespace std;
const int oo=1e9;
/**oo 表示无穷大*/
const int mm=200007;
/**mm 表示边的最大数量,记住要是原图的两倍,在加边的时候都是双向的*/
const int mn=1007;
/**mn 表示点的最大数量*/
int node,src,dest,edge;
/**node 表示节点数,src 表示源点,dest 表示汇点,edge 统计边数*/
int ver[mm],flow[mm],nxt[mm];
/**ver 边指向的节点,flow 边的容量,nxt 链表的下一条边*/
int head[mn],work[mn],dis[mn],q[mn];
/**head 节点的链表头,work 用于算法中的临时链表头,dis 计算距离*/
/**初始化链表及图的信息*/
void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
memset(head,-1,sizeof(head));
edge=0;
}
/**增加一条u 到v 容量为c 的边*/
void addedge(int u,int v,int c)
{
ver[edge]=v,flow[edge]=c,nxt[edge]=head[u],head[u]=edge++;
ver[edge]=u,flow[edge]=0,nxt[edge]=head[v],head[v]=edge++;
}
/**广搜计算出每个点与源点的最短距离,如果不能到达汇点说明算法结束*/
bool Dinic_bfs()
{
int i,u,v,l,r=0;
for(i=0; i<node; ++i)dis[i]=-1;
dis[q[r++]=src]=0;
for(l=0; l<r; ++l)
for(i=head[u=q[l]]; i>=0; i=nxt[i])
if(flow[i]&&dis[v=ver[i]]<0)
{
/**这条边必须有剩余容量*/
dis[q[r++]=v]=dis[u]+1;
if(v==dest)return 1;
}
return 0;
}
/**寻找可行流的增广路算法,按节点的距离来找,加快速度*/
int Dinic_dfs(int u,int exp)
{
if(u==dest)return exp;
/**work 是临时链表头,这里用i 引用它,这样寻找过的边不再寻找*/
for(int &i=work[u],v,tmp; i>=0; i=nxt[i])
if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
{
flow[i]-=tmp;
flow[i^1]+=tmp;
/**正反向边容量改变*/
return tmp;
}
return 0;
}
int Dinic_flow()
{
int i,ret=0,delta;
while(Dinic_bfs())
{
for(i=0; i<node; ++i)work[i]=head[i];
while(delta=Dinic_dfs(src,oo))ret+=delta;
}
return ret;
}
const int MAXN = 1007;
int heads[MAXN];
int cnt;
struct edge{
int v;
int nxt;
int cost;
}Es[200007];
int d[MAXN];
void init(){
cnt = 0;
memset(heads,-1,sizeof(heads));
}
inline void add_edge(int i,int j,int cost){
Es[cnt].v = j;
Es[cnt].cost = cost;
Es[cnt].nxt = heads[i];
heads[i] = cnt++;
}
void spfa(int x){
memset(d,0x3f,sizeof(d));
int instack[MAXN];
memset(instack,0,sizeof(instack));
d[x] = 0;
queue<int> Q;
Q.push(x);
instack[x] = 1;
while(!Q.empty()){
int u = Q.front();Q.pop();
for(int e = heads[u];e != -1;e = Es[e].nxt){
int v = Es[e].v;
int cost = Es[e].cost;
if(d[v] > d[u] + cost){
d[v] = d[u] + cost;
if(!instack[v]){
instack[v] = 1;
Q.push(v);
}
}
}
instack[u] = 0;
}
}
int visit[200007];
void dfs(int x){
for(int e = heads[x];e != -1;e = Es[e].nxt){
int v = Es[e].v;
if(d[v] == d[x] + Es[e].cost){
if(!visit[e]){
visit[e] = 1;
addedge(x-1,v-1,1);
dfs(v);
}
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
init();
int n,m;
scanf("%d%d",&n,&m);
for(int i = 0;i < m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a == b) continue;
add_edge(a,b,c);
}
int beg,tar;
scanf("%d%d",&beg,&tar);
prepare(n,beg-1,tar-1);
spfa(beg);
memset(visit,0,sizeof(visit));
dfs(beg);
int ans = Dinic_flow();
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- hdu 3416 Marriage Match IV 【图论-网络流-最短路+最大流(spfa + Dinic)】
- HDU3416 Marriage Match IV(最短路,网络流,最大流,SPFA,ISAP算法)
- Marriage Match IV (hdu 3416 网络流+spfa最短路)
- hdu3416 Marriage Match IV(网络流+最短路)
- HDU ~ 3416 ~ Marriage Match IV (最短路Dijkstra + 网络流Dinic)
- bzoj1001 [BeiJing2006]狼抓兔子(网络流dinic算法||最短路spfa)
- HDU 3416 Marriage Match IV(最短路+网络流之最大流)
- 图论总结 Dijkstra Tarjan 最小生成树 二分图 最短路 强连通分量 双连通分量 Bellman-Ford SPFA 二分图染色 Kruskal Prim 网络流 二分图匹配 Dinic
- HDU 3416 Marriage Match IV(最短路,网络流)
- 最短路模板BF和SPFA,poj3259测
- Remmarguts' Date POJ - 2449 第k短路 SPFA+A*
- hdu4396 spfa有限制的最短路
- 【原创】最短路模板 Floyd,优先队列优化dijkstra,SPFA
- HDU 1690(Bus System) 最短路(SPFA&&FLOYD)
- 最短路-SPFA
- HDU2112 最短路入门题 spfa
- 【强联通分量缩点】【最短路】【spfa】bzoj1179 [Apio2009]Atm
- POJ - 3259 Wormholes(SPFA最短路判断负环)
- HDU2544最短路(最短路 Dijkstra, spfa)
- 【最短路】【spfa】hdu6071 Lazy Running