比赛链接:
http://acm.hdu.edu.cn/search.php?field=problem&key=2019+Multi-University+Training+Contest+1&source=1&searchmode=source
hdu6582
题意:
删除某些边,让$1$到$n$的最短路径发生变化
删除某条边的费用是边的长度
分析:
先用迪杰斯特拉跑一遍整个图,满足$dis[a]+w=dis[b]$的边,肯定是最短路径上的边
选出这些边,找到一个最小割集,Dinic比EK快很多,虽然渐进复杂度相同,都是$O(nm^2)$
Dinic加上弧优化后速度更快
ac代码(Dinic没有弧优化):
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define pa pair<ll,ll> using namespace std; const ll maxn=1e4+5; const ll maxm=1e7+10; const ll mod=1e9+7; vector<pair<int,int>>ve[maxn]; ll dis[maxn]; int n,m,edge_num=-1,head[maxn],dep[maxn]; bool vis[maxn]; struct Edge{ int to,nex,v; }edge[maxn*2];//maxn=1e4 void add_edge(int a,int b,int c)//边数从0开始,每次加上反向边,这样奇偶交替加边,重边无所谓 { edge[++edge_num].to=b; edge[edge_num].nex=head[a]; edge[edge_num].v=c; head[a]=edge_num; } bool bfs() { for(int i=1;i<=n;i++)dep[i]=1e9; dep[1]=0; queue<int>que; que.push(1); while(que.size()){ int now=que.front(); que.pop(); for(int i=head[now];i!=-1;i=edge[i].nex){ int to=edge[i].to; int v=edge[i].v; if(v&&dep[to]>dep[now]+1){ dep[to]=dep[now]+1; que.push(to); } } } if(dep[n]==1e9)return false; else return true; } int dfs(int x,int lowflow) { if(x==n||lowflow==0)return lowflow; int reslow=0; int used=0; for(int i=head[x];i!=-1;i=edge[i].nex){ int to=edge[i].to; if(edge[i].v&&dep[x]+1==dep[to]){ if(reslow=dfs(to,min(lowflow,edge[i].v))){ edge[i].v-=reslow; edge[i^1].v+=reslow; used+=reslow; lowflow-=reslow; if(lowflow<=0)break; } } } return used; } void Dinic() { ll maxflow=0; int lowflow; while(bfs()){ while(lowflow=dfs(1,1e9)){ maxflow+=lowflow; } } printf("%lld\n",maxflow); } void dj() { for(int i=1;i<=n;i++)dis[i]=1e18,vis[i]=false; dis[1]=0; priority_queue<pair<ll,int>>que; que.push(make_pair(0,1)); while(que.size()){ pair<ll,int>now=que.top(); que.pop(); if(vis[now.second])continue; vis[now.second]=true; for(int i=0;i<ve[now.second].size();i++){ int to=ve[now.second][i].first; int w=ve[now.second][i].second; if(dis[to]>dis[now.second]+w){ dis[to]=dis[now.second]+w; que.push(make_pair(-dis[to],to)); } } } } int main() { // freopen("D:/a.txt","w",stdout); // freopen("D:/2.txt","r",stdin); int T; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); for(int i=1;i<=m;i++){ int a,b,c; scanf("%d %d %d",&a,&b,&c); ve[a].push_back(make_pair(b,c)); } dj(); if(dis[n]==1e18){ printf("0\n"); continue; } for(int i=1;i<=n;i++)head[i]=-1; edge_num=-1; for(int i=1;i<=n;i++){ for(int j=0;j<ve[i].size();j++){ int a=i,b=ve[i][j].first,c=ve[i][j].second; if(dis[a]+c==dis[b])add_edge(a,b,c),add_edge(b,a,0); } } Dinic(); for(int i=1;i<=n;i++)ve[i].clear(); } return 0; }
ac代码(Dinic弧优化):
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define pa pair<ll,ll> using namespace std; const ll maxn=1e4+5; const ll maxm=1e7+10; const ll mod=1e9+7; vector<pair<int,int>>ve[maxn]; ll dis[maxn]; int n,m,edge_num=-1,head[maxn],dep[maxn],cur[maxn]; bool vis[maxn]; struct Edge{ int to,nex,v; }edge[maxn*2];//maxn=1e4 void add_edge(int a,int b,int c)//边数从0开始,每次加上反向边,这样奇偶交替加边,重边无所谓 { edge[++edge_num].to=b; edge[edge_num].nex=head[a]; edge[edge_num].v=c; head[a]=edge_num; } bool bfs()//分层 { for(int i=1;i<=n;i++)dep[i]=1e9; dep[1]=0; queue<int>que; que.push(1); while(que.size()){ int now=que.front(); que.pop(); for(int i=head[now];i!=-1;i=edge[i].nex){ int to=edge[i].to; int v=edge[i].v; if(v&&dep[to]>dep[now]+1){ dep[to]=dep[now]+1; que.push(to); } } } if(dep[n]==1e9)return false; else return true; } int dfs(int x,int lowflow) { if(x==n||lowflow==0)return lowflow; int reslow=0; int used=0; for(int &i=cur[x];i!=-1;i=edge[i].nex){ int to=edge[i].to; if(edge[i].v&&dep[x]+1==dep[to]){ if(reslow=dfs(to,min(lowflow,edge[i].v))){ edge[i].v-=reslow; edge[i^1].v+=reslow; used+=reslow; lowflow-=reslow; if(lowflow<=0)break; } } } return used; } void Dinic() { ll maxflow=0; int lowflow; while(bfs()){ for(int i=1;i<=n;i++)cur[i]=head[i]; while(lowflow=dfs(1,1e9)){ maxflow+=lowflow; } } printf("%lld\n",maxflow); } void dj() { for(int i=1;i<=n;i++)dis[i]=1e18,vis[i]=false; dis[1]=0; priority_queue<pair<ll,int>>que; que.push(make_pair(0,1)); while(que.size()){ pair<ll,int>now=que.top(); que.pop(); if(vis[now.second])continue; vis[now.second]=true; for(int i=0;i<ve[now.second].size();i++){ int to=ve[now.second][i].first; int w=ve[now.second][i].second; if(dis[to]>dis[now.second]+w){ dis[to]=dis[now.second]+w; que.push(make_pair(-dis[to],to)); } } } } int main() { // freopen("D:/a.txt","w",stdout); // freopen("D:/2.txt","r",stdin); int T; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); for(int i=1;i<=m;i++){ int a,b,c; scanf("%d %d %d",&a,&b,&c); ve[a].push_back(make_pair(b,c)); } dj(); if(dis[n]==1e18){ printf("0\n"); continue; } for(int i=1;i<=n;i++)head[i]=-1; edge_num=-1; for(int i=1;i<=n;i++){ for(int j=0;j<ve[i].size();j++){ int a=i,b=ve[i][j].first,c=ve[i][j].second; if(dis[a]+c==dis[b])add_edge(a,b,c),add_edge(b,a,0); } } Dinic(); for(int i=1;i<=n;i++)ve[i].clear(); } return 0; }
原文地址:https://www.cnblogs.com/carcar/p/11231075.html
时间: 2024-11-09 05:46:46