# Marriage Match IV

http://acm.hdu.edu.cn/showproblem.php?pid=3416

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6081    Accepted Submission(s): 1766

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
```  1 #include<iostream>
2 #include<cstring>
3 #include<string>
4 #include<cmath>
5 #include<cstdio>
6 #include<algorithm>
7 #include<queue>
8 #include<vector>
9 #include<set>
10 #define maxn 100005
11 #define MAXN 10005
12 #define mem(a,b) memset(a,b,sizeof(a))
13 const int N=200005;
14 const int M=200005;
15 const int INF=0x3f3f3f3f;
16 using namespace std;
18 {
19     char ch=' ';
20     int ans=0;
21     while(ch<'0' || ch>'9')
22         ch=getchar();
23     while(ch<='9' && ch>='0')
24     {
25         ans=ans*10+ch-'0';
26         ch=getchar();
27     }
28     return ans;
29 }
30 int n;
31 vector<pair<int,int> >ve[maxn];
32 int dis[maxn],dis1[maxn],dis2[maxn],vis[maxn];
33 int a[maxn],b[maxn],c[maxn];
34 struct sair{
35     int pos,len;
36     friend bool operator<(sair a,sair b){
37         return a.len>b.len;
38     }
39 };
40
41
42 void Dijstra(int s){
43     for(int i=0;i<=n;i++){
44         dis[i]=INF;
45         vis[i]=0;
46     }
47     priority_queue<sair>Q;
48     sair tmp;
49     tmp.pos=s,tmp.len=0;
50     Q.push(tmp);
51     dis[s]=0;
52     int now,Ne,len;
53     while(!Q.empty()){
54         tmp=Q.top();
55         Q.pop();
56         now=tmp.pos;
57         if(!vis[now]){
58             vis[now]=1;
59             for(int i=0;i<ve[now].size();i++){
60                 Ne=ve[now][i].first;
61                 len=ve[now][i].second;
62                 if(dis[Ne]>dis[now]+len){
63                     dis[Ne]=dis[now]+len;
64                     tmp.pos=Ne;
65                     tmp.len=dis[Ne];
66                     Q.push(tmp);
67                 }
68             }
69         }
70     }
71 }
72
73
74 struct Edge{
75     int v,next;
76     int cap,flow;
77 }edge[MAXN*20];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
78 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
79 int cnt=0;//实际存储总边数
80 void isap_init()
81 {
82     cnt=0;
83     memset(pre,-1,sizeof(pre));
84 }
85 void isap_add(int u,int v,int w)//加边
86 {
87     edge[cnt].v=v;
88     edge[cnt].cap=w;
89     edge[cnt].flow=0;
90     edge[cnt].next=pre[u];
91     pre[u]=cnt++;
92 }
93 void add(int u,int v,int w){
96 }
97 bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里，但是好像是时间要长
98 {
99     memset(dep,-1,sizeof(dep));
100     memset(gap,0,sizeof(gap));
101     gap[0]=1;
102     dep[t]=0;
103     queue<int>q;
104     while(!q.empty())
105     q.pop();
106     q.push(t);//从汇点开始反向建层次图
107     while(!q.empty())
108     {
109         int u=q.front();
110         q.pop();
111         for(int i=pre[u];i!=-1;i=edge[i].next)
112         {
113             int v=edge[i].v;
114             if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs，但应该判断正向弧的余量
115             {
116                 dep[v]=dep[u]+1;
117                 gap[dep[v]]++;
118                 q.push(v);
119                 //if(v==sp)//感觉这两句优化加了一般没错，但是有的题可能会错，所以还是注释出来，到时候视情况而定
120                 //break;
121             }
122         }
123     }
124     return dep[s]!=-1;
125 }
126 int isap(int s,int t)
127 {
128     if(!bfs(s,t))
129     return 0;
130     memcpy(cur,pre,sizeof(pre));
131     //for(int i=1;i<=n;i++)
132     //cout<<"cur "<<cur[i]<<endl;
133     int u=s;
134     path[u]=-1;
135     int ans=0;
136     while(dep[s]<n)//迭代寻找增广路
137     {
138         if(u==t)
139         {
140             int f=INF;
141             for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路
142                 f=min(f,edge[i].cap-edge[i].flow);
143             for(int i=path[u];i!=-1;i=path[edge[i^1].v])
144             {
145                 edge[i].flow+=f;
146                 edge[i^1].flow-=f;
147             }
148             ans+=f;
149             u=s;
150             continue;
151         }
152         bool flag=false;
153         int v;
154         for(int i=cur[u];i!=-1;i=edge[i].next)
155         {
156             v=edge[i].v;
157             if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow)
158             {
159                 cur[u]=path[v]=i;//当前弧优化
160                 flag=true;
161                 break;
162             }
163         }
164         if(flag)
165         {
166             u=v;
167             continue;
168         }
169         int x=n;
170         if(!(--gap[dep[u]]))return ans;//gap优化
171         for(int i=pre[u];i!=-1;i=edge[i].next)
172         {
173             if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
174             {
175                 x=dep[edge[i].v];
176                 cur[u]=i;//常数优化
177             }
178         }
179         dep[u]=x+1;
180         gap[dep[u]]++;
181         if(u!=s)//当前点没有增广路则后退一个点
182         u=edge[path[u]^1].v;
183      }
184      return ans;
185 }
186
187 int main(){
188     int T;
190     while(T--){
191         int m;
194         for(int i=1;i<=n;i++){
195             ve[i].clear();
196         }
197         for(int i=1;i<=m;i++){
201         }
202         int s,t;
205         for(int i=1;i<=m;i++){
206              if(a[i]!=b[i])
207             ve[a[i]].push_back(make_pair(b[i],c[i]));
208         }
209         Dijstra(s);
210         memcpy(dis1,dis,sizeof(dis));
211         for(int i=1;i<=n;i++){
212             ve[i].clear();
213         }
214         for(int i=1;i<=m;i++){
215             if(a[i]!=b[i])
216             ve[b[i]].push_back(make_pair(a[i],c[i]));
217         }
218         Dijstra(t);
219         memcpy(dis2,dis,sizeof(dis));
220         isap_init();
221         for(int i=1;i<=m;i++){
222             if(a[i]!=b[i]&&dis1[a[i]]+dis2[b[i]]+c[i]==dis1[t]){
224             }
225         }
226         int ans=0;
227         ans=isap(s,t);
228         printf("%d
",ans);
229     }
230 }```
View Code
• 相关阅读:
递归
Python 实例方法、类方法、静态方法的区别与作用
内置函数和匿名函数
迭代器和生成器
函数动态传参详细，作用域和名称空间，global和nonlocal
初识函数（定义，语法，返回值，参数）
pycharm快捷键第二弹
pycharm快捷键
bmp图片显示
jpg图片在开发板上显示
• 原文地址：https://www.cnblogs.com/Fighting-sh/p/9936728.html