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?
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.
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 }
posted on 2018-11-09 19:12 Fighting_sh 阅读(535) 评论(0) 编辑 收藏 举报