HDU_3416_Marriage Match IV(最短路+最大流)
2015-09-17 09:27
441 查看
Marriage Match IV
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2728 Accepted Submission(s): 826
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
题意:有向图中,从起点A走到终点B,每条路只能一次,问最多能走多少次最短路。
分析:最短路+最大流。先用最短路预处理出起点与终点到所有点的最短路,然后对于所有的边(u,v,d)判断一下是否在最短路径上(dis[s][u]+d+dis[t][v]==dis[u][t]),保留下这些有用边,容量都为1,然后跑一遍最大流即可。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416
代码清单:
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<cctype> #include<string> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; #define end() return 0 typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; const int maxN = 1000 + 5; const int maxn = 10000 + 5; const int maxv = 100000 + 5; const int INF = 0x7f7f7f7f; struct Edge{ int from,to,cap,flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} }; struct dinic{ int n,m,s,t; //结点数,边数(包括反向弧),源点,汇点 vector<Edge>edge;//边表。edge[e]和edge[e^1]互为反向弧 vector<int>G[maxn];//邻接表。G[i][j]表示结点i的第j条边在e数组的序号 bool vis[maxn]; //bfs用 int d[maxn]; //从起点到i的距离 int cur[maxn]; //当前弧下标 void init(int n,int s,int t){ this -> n = n; this -> s = s; this -> t = t; for(int i=0;i<=n;i++) G[i].clear(); edge.clear(); } void addEdge(int from,int to,int cap){ edge.push_back(Edge(from,to,cap,0)); edge.push_back(Edge(to,from,0,0)); m=edge.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool bfs(){ memset(vis,false,sizeof(vis)); queue<int>q; q.push(s); d[s]=0; vis[s]=true; while(!q.empty()){ int x=q.front();q.pop(); for(int i=0;i<G[x].size();i++){ Edge& e=edge[G[x][i]]; if(!vis[e.to]&&e.cap>e.flow){ //只考虑残量网络中的弧 vis[e.to]=true; d[e.to]=d[x]+1; q.push(e.to); } } } return vis[t]; } int dfs(int x,int a){ if(x==t||a==0) return a; int flow=0,f; for(int& i=cur[x];i<G[x].size();i++){ // & -> 从上次考虑的弧 Edge& e=edge[G[x][i]]; if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){ e.flow+=f; edge[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0) break; } } return flow; } int maxflow(){ int flow=0; while(bfs()){ memset(cur,0,sizeof(cur)); flow+=dfs(s,INF); } return flow; } }; struct EDGE{ int to,dis; EDGE(){} EDGE(int v,int d):to(v),dis(d){} }; int T; int N,M,st,ta; int A[maxv],B[maxv],C[maxv]; vector<EDGE>graph[maxN]; int dist[2][maxN]; bool vist[maxN]; dinic dc; void input(){ scanf("%d%d",&N,&M); for(int i=1;i<=N;i++) graph[i].clear(); for(int i=1;i<=M;i++){ scanf("%d%d%d",&A[i],&B[i],&C[i]); graph[A[i]].push_back(EDGE(B[i],C[i])); } scanf("%d%d",&st,&ta); } void spfa(int s){ int pose=(s==st)?0:1; memset(dist[pose],INF,sizeof(dist[pose])); memset(vist,false,sizeof(vist)); queue<int>q; while(!q.empty()) q.pop(); dist[pose][s]=0; vist[s]=true; q.push(s); while(!q.empty()){ int p=q.front();q.pop(); vist[p]=false; for(int i=0;i<graph[p].size();i++){ EDGE& e=graph[p][i]; if(dist[pose][e.to]>dist[pose][p]+e.dis){ dist[pose][e.to]=dist[pose][p]+e.dis; if(!vist[e.to]){ vist[e.to]=true; q.push(e.to); } } } } } void createGraph(){ dc.init(N,st,ta); for(int i=1;i<=M;i++){ if(dist[0][A[i]]+dist[1][B[i]]+C[i]==dist[0][ta]){ dc.addEdge(A[i],B[i],1); } } } void solve(){ spfa(st); for(int i=1;i<=N;i++) graph[i].clear(); for(int i=1;i<=M;i++) graph[B[i]].push_back(EDGE(A[i],C[i])); spfa(ta); createGraph(); printf("%d\n",dc.maxflow()); } int main(){ scanf("%d",&T); while(T--){ input(); solve(); }end(); }
相关文章推荐
- JNotify文件变化通知
- Nearly prime numbers - SGU 113(素数)
- 大众点评—笔试
- (四)工厂方法模式
- lib文件配置的3种方法
- 软件测试
- Git 常用命令速查表(三)
- Xcode6.4 插件管理工具Alcatraz安装和常用插件
- 存储系统科普——硬件层介绍
- winForm
- NetBeans表格
- 微信官方:我们是如何打败QQ的?
- Group Anagrams
- Android自定义控件——时钟、进度条
- 电话本3.0 I/O流实现
- Linux 运维工程师的十个基本技能点
- Struts2通配符映射
- Z表数据EXCEL导入
- [刷题]Single Number II
- 树莓派开发(SD卡删除分区)