HDU 3416-Marriage Match IV(最短路+最大流)
阿新 • • 發佈:2018-12-09
很好的一道題,求的是沒有交集的最短路的條數。
正向反向跑兩邊SPFA之後,對於輸入的邊,如果此條邊在最短路上,那麼就講它的容量+1,最後根據重新構造的圖跑一遍最大流。
有意思的是這道題卡了我之前寫的一個dinic演算法的模板,具體程式碼可見:這裡
程式碼如下:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<queue> #define memset(a,v) memset(a,v,sizeof(a)) #define min(a,b) (a<b?a:b) #define eps 1.0E-8 using namespace std; const int MAXL(1e3); const int INF(0x7f7f7f7f); const int mod(1e9+7); typedef long long int LL; struct node { int to,next,cap; node() {} node(int to,int next,int cap):to(to),next(next),cap(cap) {} } edge[800*MAXL+50],in[100*MAXL+50]; int head1[2][MAXL+50]; int head[MAXL+50]; int level[MAXL+50]; int vis[MAXL+50]; int dis[2][MAXL+50]; int n,m,cnt; int BFS(int sc,int st) { queue<int>q; memset(level,0); level[sc]=1; q.push(sc); while(!q.empty()) { int u=q.front(); q.pop(); if(u==st) return 1; for(int i=head[u]; ~i; i=edge[i].next) { int v=edge[i].to,c=edge[i].cap; if(!level[v] && c) level[v]=level[u]+1,q.push(v); } } return 0; } int dfs(int u,int des,int increaseRoad) { if(u==des) return increaseRoad; int ret=0; for(int k=head[u]; k!=-1; k=edge[k].next) { int v = edge[k].to,w=edge[k].cap; if(level[v]==level[u]+1&&w!=0) { int MIN = min(increaseRoad-ret,w); w = dfs(v,des,MIN); if(w > 0) { edge[k].cap-=w; edge[k^1].cap+=w; ret+=w; if(ret==increaseRoad) return ret; } } } return ret; } int dinic(int sc,int st) { int ans=0; while(BFS(sc,st)) ans+=dfs(sc,st,INF); return ans; } void SPFA(int sc,int st,int dimen) { queue<int>q; memset(vis,0); memset(dis[dimen],INF); vis[sc]=1; dis[dimen][sc]=0; q.push(sc); while(!q.empty()) { int v=q.front(); q.pop(); vis[v]=0; for(int i=head1[dimen][v]; ~i; i=edge[i].next) { int x=edge[i].to; if(dis[dimen][x]>dis[dimen][v]+edge[i].cap) { dis[dimen][x]=dis[dimen][v]+edge[i].cap; if(!vis[x]) { vis[x]=1; q.push(x); } } } } } void add_edge1(int u,int v,int w,int dimen) { edge[cnt]=node(v,head1[dimen][u],w); head1[dimen][u]=cnt++; } void add_edge(int u,int v,int w) { edge[cnt]=node(v,head[u],w); head[u]=cnt++; } void build_newGraph(int sc,int st) { cnt=0; memset(head,-1); for(int i=1; i<=m; i++) { int u=in[i].to,v=in[i].next,path=in[i].cap; if(dis[0][u]+path+dis[1][v]==dis[0][st]) add_edge(u,v,1),add_edge(v,u,0); } } int main() { int T; scanf("%d",&T); while(T--) { cnt=0; memset(head1,-1); scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); in[i]=node(x,y,z); add_edge1(x,y,z,0); add_edge1(y,x,z,1); } int sc,st; scanf("%d%d",&sc,&st); SPFA(sc,st,0); SPFA(st,sc,1); build_newGraph(sc,st); int ans=dinic(sc,st); printf("%d\n",ans); } }