HDU6582 Path(最短路+最小割)
题意:
查询一个边集,使得这个图里起点到终点的最短路径变长。
题解:
先用spfa跑一遍最短路,把不在最短路径上的边权设为0,然后跑一遍Dinic算法求最大流/最小割。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef long long ll; const ll inf=1e18; const int maxn=1e5; int N,M,T; int head[maxn]; int tol; struct node { int u; int v; ll w; int next; }edge[maxn]; void addedge (int u,int v,ll w) { edge[tol].u=u; edge[tol].v=v; edge[tol].w=w; edge[tol].next=head[u]; head[u]=tol++; } ll d[maxn]; int visit[maxn]; void spfa (int s) { for (int i=1;i<=N;i++) d[i]=inf; d[s]=0; queue<int> q; q.push(s); visit[s]=1; while (!q.empty()) { int u=q.front(); q.pop(); visit[u]=0; for (int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if (edge[i].w>0&&d[v]>d[u]+edge[i].w) { d[v]=d[u]+edge[i].w; if (!visit[v]) { q.push(v); visit[v]=1; } } } } } ll dep[maxn]; ll inque[maxn]; ll vi; ll cur[maxn]; ll maxflow=0; int s,t; bool bfs () { for (int i=0;i<=N;i++) cur[i]=head[i],dep[i]=inf,inque[i]=0; dep[s]=0; queue<int> q; q.push(s); while (!q.empty()) { int u=q.front(); q.pop(); inque[u]=0; for (int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if (dep[v]>dep[u]+1&&edge[i].w) { dep[v]=dep[u]+1; if (inque[v]==0) { q.push(v); inque[v]=1; } } } } if (dep[t]!=inf) return 1; return 0; } ll dfs (int u,ll flow) { ll increase=0; if (u==t) { vi=1; maxflow+=flow; return flow; } ll used=0; for (int i=cur[u];i!=-1;i=edge[i].next) { cur[u]=i; int v=edge[i].v; if (edge[i].w&&dep[v]==dep[u]+1) { if (increase=dfs(v,min(flow-used,edge[i].w))) { used+=increase; edge[i].w-=increase; edge[i^1].w+=increase; if (used==flow) break; } } } return used; } ll Dinic () { while (bfs()) { vi=1; while (vi==1) { vi=0; dfs(s,inf); } } return maxflow; } int main () { scanf("%d",&T); while (T--) { memset(head,-1,sizeof(head)); tol=0; maxflow=0; scanf("%d%d",&N,&M); for (int i=1;i<=M;i++) { int u,v; ll w; scanf("%d%d%lld",&u,&v,&w); addedge(u,v,w); addedge(v,u,0); } spfa(1); for (int i=1;i<=N;i++) { for (int j=head[i];j!=-1;j=edge[j].next) if (d[edge[j].v]!=d[i]+edge[j].w) edge[j].w=0; } s=1; t=N; printf("%lld\n",Dinic()); } return 0; }