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为目的地),也就是 该边的起点到出发点的最短距离+边的终点到目的地的最短距离+起点到终点的距离 == 出发点到目的地的最短距离 ,则将该边加入到网络图中。可自己在纸上画画便可知道。
代码写得很搓,留给自己反省反省。
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 }