- 题意:
- 给出一个无向连通图,每条边的权值都是1,可存在重边,a在1节点,b在n节点。
- 问你最少花费多少代价能将1到n的路径最远,如果不存在路径,输出0就行
- 题解:
- 先求出最短路,然后保留所有满足 dey dex = ew 的边,对于新的图求 1 到 n 的最小
- 割即为答案,最小割模板第一次用。
- 代码:
#include <bits/stdc++.h> using namespace std; #define ll long long const ll inf = 1e16; const int maxx = 1e4+5; const int inf_int = 1e9+5; struct node{ ll d; int x; bool operator<(const node &b)const { return d>b.d; } }; int n,m,xx[maxx],yy[maxx],cc[maxx]; vector< pair<int,int> > GG[maxx]; priority_queue<node> q; bool vis[maxx]; ll dis[maxx],dis2[maxx]; void dijk(int s,ll *d) { int u,v,w,len; node tmp; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) d[i] = inf; d[s] = 0; q.push((node){0,s}); while(!q.empty()) { tmp = q.top(); q.pop(); u = tmp.x; if(vis[u]) continue; vis[u] = true; len = GG[u].size(); for(int i=0;i<len;i++) { v=GG[u][i].first; w=GG[u][i].second; if(d[v] > d[u]+w) { d[v]=d[u]+w; q.push((node){d[v],v}); } } } return ; } //最大流和最小割模板 struct edge{ int to,cap,rev; }; vector<edge> G[maxx]; int leval[maxx]; int iter[maxx]; void add(int from,int to,int cap) { G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1}); return ; } void bfs(int s) { memset(leval,-1,sizeof(leval)); queue<int> que; leval[s] = 0; que.push(s); while(!que.empty()) { int v = que.front(); que.pop(); for(int i=0;i<G[v].size();i++) { edge &e=G[v][i]; if(e.cap>0&&leval[e.to]<0) { leval[e.to]=leval[v]+1; que.push(e.to); } } } return ; } int dfs(int v,int t,int f) { if(v==t) return f; for(int &i=iter[v];i<G[v].size();i++) { edge &e = G[v][i]; if(e.cap>0&&leval[v]<leval[e.to]) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap -=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int Dinic(int s,int t) { int flow=0; while(1) { bfs(s); if(leval[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,inf_int))>0) flow+=f; } } int main() { int t; cin>>t; while(t--) { cin>>n>>m; for(int i=1;i<=m;i++) { scanf("%d%d%d",&xx[i],&yy[i],&cc[i]); GG[xx[i]].push_back( pair<int,int>(yy[i],cc[i]) ); } dijk(1,dis); for(int i=1;i<=n;i++) GG[i].clear(); for(int i=1;i<=m;i++) GG[yy[i]].push_back( pair<int,int>(xx[i],cc[i]) ); dijk(n,dis2); for(int i=1;i<=m;i++) { if(dis[xx[i]] + cc[i] + dis2[yy[i]] == dis[n]) add(xx[i],yy[i],cc[i]); }//构建一个新的图 cout<<Dinic(1,n)<<endl; for(int i=1;i<=n;i++) { GG[i].clear(); G[i].clear(); } } return 0; }