Marriage Match IV(最短路+网络流)

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;
 17 inline int read()
 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){
 94     isap_add(u,v,1);
 95     isap_add(v,u,0);
 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;
189     T=read();
190     while(T--){
191         int m;
192         n=read();
193         m=read();
194         for(int i=1;i<=n;i++){
195             ve[i].clear();
196         }
197         for(int i=1;i<=m;i++){
198             a[i]=read();
199             b[i]=read();
200             c[i]=read();
201         }
202         int s,t;
203         s=read();
204         t=read();
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]){
223                 add(a[i],b[i],1);
224             }
225         }
226         int ans=0;
227         ans=isap(s,t);
228         printf("%d\n",ans);
229     }
230 }
View Code

 

posted on 2018-11-09 19:12  Fighting_sh  阅读(535)  评论(0编辑  收藏  举报

导航