HDU 3416 最短路+最大流

来源:互联网 发布:成都医疗大数据公司 编辑:程序博客网 时间:2024/05/17 20:35

Marriage Match IV

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1486    Accepted Submission(s): 416

 

Problem Description

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,第一次求出各点离出发点A的最短路,存在数组lowA[]中;第二次求出各点离目的地B的最短路,存到数组lowB[]中(此时要注意,因为边是单向边,此次求spfa时,松弛时要注意,若输入边的时候存边用数组map[i][j]存,那么第二次spfa时应该将下标互换,详细可见代码;构图时,枚举所有边,如果该边的起点为a,终点为b,边长为c,则若满足lowA[a]+lowB[b]+c == lowA[B](B为目的地),也就是  该边的起点到出发点的最短距离+边的终点到目的地的最短距离+起点到终点的距离 == 出发点到目的地的最短距离 ,则将该边加入到网络图中。可自己在纸上画画便可知道。

代码写得很搓,留给自己反省反省。

View Code
  1 #include <iostream>  2 #include <cstdio>  3 #include <cstring>  4 #include <cmath>  5 #include <queue>  6 #include <algorithm>  7 #define INF 100000005  8 #define MAX 1005  9  10 using namespace std; 11  12 struct node 13 { 14     int to,val,next; 15 }; 16  17 int T,N,M,A,B; 18  19 int map[MAX][MAX];  //存路径的链接情况 20 int st[MAX*105],ed[MAX*105],cost[MAX*105]; //存所有的边,从左到右分别是边的起点,终点,长度 21 int lowA[MAX],lowB[MAX];  //存各点到A的最短路径,各点到B的最短路径 22 bool inQueue[MAX];  23  24 node edge[MAX * MAX]; 25 int head[MAX]; 26 int idx; 27  28 int dis[MAX]; 29 int gap[MAX]; 30  31 void addNode(int from,int to,int val) 32 { 33     edge[idx].to = to; 34     edge[idx].val = val; 35     edge[idx].next = head[from]; 36     head[from] = idx ++; 37     edge[idx].to = from; 38     edge[idx].val = 0; 39     edge[idx].next = head[to]; 40     head[to] = idx ++; 41 } 42  43 void spfa_A() 44 { 45     queue <int> Q; 46     for(int i=1; i<MAX; i++) 47     { 48         lowA[i] = INF; 49         inQueue[i] = false; 50     } 51     lowA[A] = 0; 52     inQueue[A] = true; 53     Q.push(A); 54     while(!Q.empty()) 55     { 56         int temp = Q.front(); 57         Q.pop(); 58         inQueue[temp] = false; 59         for(int i=1; i<=N; i++) 60         { 61             if(lowA[i] > lowA[temp] + map[temp][i]) 62             { 63                 lowA[i] = lowA[temp] + map[temp][i]; 64                 if(!inQueue[i]) 65                 { 66                     Q.push(i); 67                     inQueue[i] = true; 68                 } 69             } 70         } 71     } 72 } 73  74 void spfa_B() 75 { 76     queue <int> Q; 77     for(int i=1; i<MAX; i++) 78     { 79         lowB[i] = INF; 80         inQueue[i] = false; 81     } 82     lowB[B] = 0; 83     inQueue[B] = true; 84     Q.push(B); 85     while(!Q.empty()) 86     { 87         int temp = Q.front(); 88         Q.pop(); 89         inQueue[temp] = false; 90         for(int i=1; i<=N; i++) 91         { 92             if(lowB[i] > lowB[temp] + map[i][temp]) //松弛时该注意单向边的影响,区别与spfa_A() 93             { 94                 lowB[i] = lowB[temp] + map[i][temp]; 95                 if(!inQueue[i]) 96                 { 97                     Q.push(i); 98                     inQueue[i] = true; 99                 }100             }101         }102     }103 }104 105 //以下是ISAP求最大流106 int dfs(int cur,int cur_val)  107 {108     if(cur == B)109         return cur_val;110     int min_dis = N-1, temp_val = cur_val;111     for(int i=head[cur]; i!=-1; i=edge[i].next)112     {113         int to = edge[i].to, value = edge[i].val;114         if(value > 0)115         {116             if(dis[to] + 1 == dis[cur])117             {118                 int val = min(temp_val,edge[i].val);119                 val = dfs(to,val);120                 temp_val -= val;121                 edge[i].val -= val;122                 edge[i^1].val += val;123                 if(dis[A] >= N)124                     return cur_val - temp_val;125                 if(temp_val == 0)126                     break;127             }128             if(dis[cur] < min_dis)129                 min_dis = dis[cur];130         }131     }132     if(cur_val == temp_val)133     {134         --gap[dis[cur]];135         if(gap[dis[cur]] == 0)136             dis[A] = N;137         dis[cur] = min_dis + 1;138         ++gap[dis[cur]];139     }140     return cur_val - temp_val;141 }142 143 int sap()144 {145     memset(gap,0,sizeof(gap));146     memset(dis,0,sizeof(dis));147     int ret = 0;148     gap[A] = N;149     while(dis[A] < N)150         ret += dfs(A,INF);151     return ret;152 }153 154 void init()155 {156     idx = 0;157     for(int i=0; i<=N; i++)158     {159         head[i] = -1;160         for(int j=0; j<=N; j++)161         {162             map[i][j] = INF;163             if(i == j)164                 map[i][j] = 0;165         }166     }167 }168 169 int main()170 {171     scanf("%d",&T);172     while(T--)173     {174         scanf("%d%d",&N,&M);175         if(M == 0)176         {177             printf("0\n");178             continue;179         }180         init();181         for(int i=1; i<=M; i++)182         {183             scanf("%d%d%d",&st[i],&ed[i],&cost[i]);184             map[st[i]][ed[i]] = min(map[st[i]][ed[i]],cost[i]);185         }186         scanf("%d%d",&A,&B);187         spfa_A();188         spfa_B();189         for(int i=1; i<=M; i++)190         {191             if(st[i]!=ed[i] && lowA[st[i]]+lowB[ed[i]]+cost[i] == lowA[B])192                 addNode(st[i],ed[i],1);193         }194         int ans = sap();195         printf("%d\n",ans);196     }197     return 0;198 }

 

 

原创粉丝点击