hdu3416:node
給一個圖,邊不能重複選,問有多少個最短路c++
hdu6582:網絡
給一個圖,問最少刪除邊權多少的邊後,最短路長度增長spa
邊不能重複選這個條件能夠想到邊權爲1,跑最大流,因此咱們能夠先跑出最短路,再把最短路中的邊做爲網絡流中的邊跑一遍最大流便可。code
最短路長度增長即最短路這個子圖再也不聯通,要使一個圖再也不聯通的最小代價顯然就是最小割,也等於最大流。it
找出最短路中的邊的方法是從s正着跑一遍最短路,再從t逆着跑一遍最短路,若是\(low[u]+rev[v]+w==low[t]\),則\((u,v)\)爲最短路中的邊。io
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e4+50; const ll INF=1e18; int T,n,m; int uu[N],vv[N]; ll ww[N]; vector<pair<int,int> > g[N]; ll low[N],rev[N]; bool vis[N]; struct node{ int v; ll c; bool operator<(const node &rhs)const{ return c>rhs.c; } }; void dijkstra(int s,ll low[]){ for(int i=1;i<=n;i++){ low[i]=INF; vis[i]=false; } low[s]=0; priority_queue<node> pq; pq.push(node{s,low[s]}); while(!pq.empty()){ node tmp=pq.top(); pq.pop(); int u=tmp.v; if(vis[u]){ continue; } vis[u]=true; int siz=g[u].size(); for(int i=0;i<siz;i++){ int v=g[u][i].first; ll w=g[u][i].second; if(!vis[v] && low[v]>low[u]+w){ low[v]=low[u]+w; pq.push(node{v,low[v]}); } } } } struct Edge{ int v,w,next; }edge[N*2]; int cnt,head[N]; void init(){ cnt=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w){ edge[cnt]=Edge{v,w,head[u]}; head[u]=cnt++; edge[cnt]=Edge{u,0,head[v]}; head[v]=cnt++; } int dep[N]; bool bfs(){ memset(dep,0,sizeof(dep)); dep[1]=1; queue<int> q; q.push(1); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; ll w=edge[i].w; if(w>0 && dep[v]==0){ dep[v]=dep[u]+1; q.push(v); } } } return dep[n]!=0; } int cur[N]; ll dfs(int u,ll flow){ if(u==n){ return flow; } for(int &i=cur[u];i!=-1;i=edge[i].next){ int v=edge[i].v; ll w=edge[i].w; if(dep[v]==dep[u]+1 && w>0){ int dis=dfs(v,min(w,flow)); if(dis>0){ edge[i].w-=dis; edge[i^1].w+=dis; return dis; } } } return 0; } ll dinic(){ ll ans=0; while(bfs()){ for(int i=1;i<=n;i++){ cur[i]=head[i]; } while(ll d=dfs(1,INF)){ ans+=d; } } return ans; } int main(void){ // freopen("in.txt","r",stdin); scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ g[i].clear(); } for(int i=0;i<m;i++){ scanf("%d%d%lld",&uu[i],&vv[i],&ww[i]); g[uu[i]].push_back({vv[i],ww[i]}); } dijkstra(1,low); for(int i=1;i<=n;i++){ g[i].clear(); } for(int i=0;i<m;i++){ g[vv[i]].push_back({uu[i],ww[i]}); } dijkstra(n,rev); init(); for(int i=0;i<m;i++){ if(uu[i]!=vv[i] && low[uu[i]]+rev[vv[i]]+ww[i]==low[n]){ add(uu[i],vv[i],ww[i]); } } ll ans=dinic(); printf("%lld\n",ans); } return 0; }