Marriage Match IV HDU3461 网络流+最短路spfa

来源:互联网 发布:知聊可以提现吗 编辑:程序博客网 时间:2024/05/16 17:59

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;} 




阅读全文
0 0
原创粉丝点击